你需要快速判断两个字符串是否可以通过循环位移使其相同。
家人们,谁懂啊,我写了三哈希还是过不了,真是服了。
结果发现哈希方案寄了,改了就过了。
FLT Orz。
我们发现两个字符串可以通过循环位移使其相同,则两个字符串循环位移所得字符串的集合必定相同。
我们把两个字符串循环位移得到的所有字符串哈希值相加判断即可。
但是这样有 Hack:AC
和 BB
。
我们发现其实两者交集不为空即可,所以我们找到一个比较有特点的量描述字符串比较好,我们改一下,用循环所得的最大哈希值代表这个字符串即可。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod=1e9+7,mod2=998244353,mod3=/*FLT老师的生日是质数,我舍去了*/;
const LL N=1e5+5;
const LL P=31;
LL T,n,m,q,x,y,hsh[N][3],K,K2,K3;
string s[N];
int main()
{
cin>>T;
while(T--)
{
cin>>n>>m;
K=1,K2=1,K3=1;
memset(hsh,0,sizeof(hsh));
for(int i=1;i<=m;i++)
{
K=K*P%mod;
K2=K2*P%mod2;
K3=K3*P%mod3;
}
for(int i=1;i<=n;i++)
{
cin>>s[i];
LL cnt=0,cnt2=0,cnt3=0;
for(int j=0;j<m;j++)
{
cnt=cnt*P%mod;
cnt=(cnt+s[i][j]-'a'+mod)%mod;
cnt2=cnt2*P%mod2;
cnt2=(cnt2+s[i][j]-'a'+mod2)%mod2;
cnt3=cnt3*P%mod2;
cnt3=(cnt3+s[i][j]-'a'+mod3)%mod3;
}
hsh[i][0]=(cnt)%mod;
hsh[i][1]=(cnt2)%mod2;
hsh[i][2]=(cnt3)%mod3;
for(int j=0;j<m-1;j++)
{
cnt=cnt*P%mod;
cnt=(cnt-K*(s[i][j]-'a')%mod+mod)%mod;
cnt=(cnt+s[i][j]-'a'+mod)%mod;
hsh[i][0]=max(hsh[i][0],cnt);
cnt2=cnt2*P%mod2;
cnt2=(cnt2-K2*(s[i][j]-'a')%mod2+mod2)%mod2;
cnt2=(cnt2+s[i][j]-'a'+mod2)%mod2;
hsh[i][1]=max(hsh[i][1],cnt2);
cnt3=cnt3*P%mod3;
cnt3=(cnt3-K3*(s[i][j]-'a')%mod3+mod3)%mod3;
cnt3=(cnt3+s[i][j]-'a'+mod3)%mod3;
hsh[i][2]=max(hsh[i][2],cnt3);
}
}
cin>>q;
while(q--)
{
cin>>x>>y;
if(hsh[x][0]==hsh[y][0]&&hsh[x][1]==hsh[y][1]&&hsh[x][2]==hsh[y][2])
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}
}
}