注意到 不是很大,考虑枚举位置进行字符串哈希。枚举 长为 的子串 ,按照题意进行重组得到 ,与 比较。
显然直接对于每个位置哈希会超时,考虑预处理如下的哈希函数( 是定值):
显然,如果 ,那么可以对哈希函数进行如下处理:
所以对于 ,考虑:
显然前后两者都可预处理,中间项直接暴力求解,复杂度 。
代码用的是另一种方式,即分解 拼接 比较,思想大同小异。
#include <cstring> #include <iostream> #include <unordered_set> using namespace std; typedef long long ll; const int max_n = 300000; const ll mod = int(1e9) + 9; char s[max_n+1], t[max_n+1]; ll sf[max_n+1]; ll qpow(ll bs, ll ix) { ll cur = 1, mul = bs, ret = 1; while (cur <= ix) { if (cur & ix) ret = (ret * mul) % mod; mul = (mul * mul) % mod; cur <<= 1; } return ret; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); int cas, k, tl; ll h, hh, mmul, mul, hhh, iv = qpow(131, mod - 2); cin >> cas; while (cas--) { cin >> s >> t >> k; if (strlen(s) != strlen(t)) { cout << "NO" << endl; continue; } if (strcmp(s, t) == 0) { cout << "YES" << endl; continue; } mul = 1, h = 0; for (int i = 0; s[i]; i++) { h = (h + mul * s[i]) % mod; mul = (mul * 131) % mod; } tl = strlen(t), sf[tl] = 0; for (int i = tl - 1; i >= k; i--) { mul = (mul * iv) % mod; sf[i] = (sf[i+1] + mul * t[i-k]) % mod; } mul = 1, hh = 0; mmul = mul, hhh = 0; for (int j = tl - k; j < tl; j++) { hhh = (hhh + mmul * t[j]) % mod; mmul = (mmul * 131) % mod; } if ((hh + sf[k] + hhh) % mod == h) { cout << "YES" << endl; goto hans; } for (int i = k; i < tl; i++) { hh = (hh + mul * t[i-k]) % mod; mmul = mul, hhh = 0; for (int j = tl - k; j < tl; j++) { mmul = (mmul * 131) % mod; hhh = (hhh + mmul * t[j]) % mod; } if ((hh + sf[i+1] + hhh) % mod == h) { cout << "YES" << endl; goto hans; } mul = (mul * 131) % mod; } cout << "NO" << endl; hans:; } return 0; }