字符串奇怪题

发布时间 2023-10-30 21:31:31作者: Zlc晨鑫

考虑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)\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})\)