字符串奇怪题

考虑S第一个字符,会和T中哪些位置上的数配对。

其实就是 \(k|S|\mod |T|\)

然后可以打表找规律:

int main() {
    int a, b;
    cin >> a >> b;
    int x = 0;
    vector<int> all;
    while (x < a * b) {
        all.push_back(x % b);
        x += a;
    }
    sort(all.begin(), all.end());
    for (int i : all) cout << i << ' ';
    return 0;
}

发现序列和\(gcd(|S|,|T|)\)有关,具体来说是\(d = gcd(|S|,|T|)\),那么先有 \(d\) 个0,\(d\)\(d\)\(d\)\(2d\) ,……,一直到\(d\)\(kd,(k+1)d\ge|T|\)

那么对于这个位置的贡献,只需要枚举\(T\)\(kd\)位置的值,判断是否相等,如果是就加上\(d\)的贡献。

比如长度分别是12和20。

x=00 0 0 0 4 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16
x=11 1 1 1 5 5 5 5 9 9 9 9 13 13 13 13 17 17 17 17
x=22 2 2 2 6 6 6 6 10 10 10 10 14 14 14 14 18 18 18 18
x=33 3 3 3 7 7 7 7 11 11 11 11 15 15 15 15 19 19 19 19
x=40 0 0 0 4 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16
……

不难发现,从x=k的地方出发,相当于以\(d\)为循环节,首项是\(k\mod d\),公差是\(d\)的数列。

写出如下无关\(n, m\)的代码:

int main() {
	cin >> a >> b >> s >> t;
	int d = gcd(s.size(), t.size());
	int res = 0;
	for (int x = 0; x < s.size(); x ++ ) {
		int cnt = 0;
		for (int y = x % d; y < t.size(); y += d)
			if (s[x] == t[y]) cnt ++ ;
		res = res + cnt * d;
	}
	cout << res << endl;
	return 0;
}

复杂度\(O(\frac{|S||T|}{d})\)

由于\(0,4,8,...\),\(1,5,9,...\),\(2,6,10,...\)\(T\)中对应的字符是一样的,产生了冗余计算,我们考虑将它们放在一起算。

我们关心的只是某个字母的出现次数,统计即可。

int main() {
	cin >> a >> b >> s >> t;
	int d = gcd(s.size(), t.size());
	int res = 0;
	for (int x = 0; x < d; x ++ ) {
		memset(cnt, 0, sizeof cnt);
		for (int i = x; i < t.size(); i += d)
			cnt[t[i] - 'a'] ++ ;
		for (int i = x; i < s.size(); i += d)
			res = res + cnt[s[i] - 'a'] * d;
	}
	cout << res << endl;
	return 0;
}

对于\(T_i\),只会在\(x = i \mod d\)的时候被枚举到一次,\(S_i\)同理。

复杂度 \(O(|S|+|T|)\)


对拍证明,上述算法是正确的。

数据生成器:

int main() {
	srand(time(0));
	int n, m;
	n=rand()%1000000+1,m=rand()%1000000+1;
	long long t=n*m/gcd(n,m);
	if (t/n>1e9||t/m>1e9) printf("%d %d\n", n, m);
	else printf("%lld %lld\n", t/n, t/m);
	while (n--) putchar(rand()%26+'a');
	putchar('\n');
	while (m--) putchar(rand()%26+'a');
	return 0;
}

PS:那个打表的证明:0.7节

posted @ 2023-10-30 21:25  Zlc晨鑫  阅读(14)  评论(0)    收藏  举报