注意到 不是很大,考虑枚举位置进行字符串哈希。枚举
长为
的子串
,按照题意进行重组得到
,与
比较。
显然直接对于每个位置哈希会超时,考虑预处理如下的哈希函数( 是定值):
显然,如果 ,那么可以对哈希函数进行如下处理:
所以对于 ,考虑:
显然前后两者都可预处理,中间项直接暴力求解,复杂度 。
代码用的是另一种方式,即分解 拼接
比较,思想大同小异。
#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;
} 
京公网安备 11010502036488号