Isomorphic Strings
题目传送门
Isomorphic Strings
题目大意
给一个字符串 s ,长度为 n ,问是否存在一个 k ,满足 k∣n ,将 s 分成相等的 k 段子串,每一段子串互为循环同构。
思路
主要是求得第一个子串的所有循环同构的哈希值集合,若第一个集合为第二个的子集,就合法
AC Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e7 +7;
const int N=5e6+6;
const int maxn=2e7;
const int base=1543;
int T, n;
char s[N];
int Hash[N],por[N];
int id[maxn],cnt;
void init(){ //初始化por数组por[0]=1;for(int i=1;i<N;i++) por[i]=1LL*por[i-1]*base%mod;
}
void get_hash(int len, char s[]){ //哈希处理总的长度的字符串for(int i=1;i<=len;i++) Hash[i]=(1LL*Hash[i-1]*base%mod+(s[i]-'a'+1))%mod;
}
int js(int l, int r){ //子串的哈希值return (Hash[r]-1LL*Hash[l-1]*por[r-l+1]%mod+mod)%mod;
}
bool solve(int d,int cnt)
{if(d==1) return 0;int len=n/d;int l=1, r=len;int tmp=js(l,r);id[tmp]=cnt;for(int i=1;i<len;i++){ //同构的其它串的hash值tmp=(1LL*js(i+1,len)*por[i]%mod +js(1,i))%mod;id[tmp]=cnt;}for(int i=1;i<=d;i++){ //判断后面的子串是否合法int x=js(l,r);if(id[x]!=cnt) return 0;l+=len, r+=len;}return 1;
}
int main()
{init();scanf("%d",&T);cnt=0;while(T--){scanf("%d",&n);scanf("%s",s+1);get_hash(n, s);int flag=0;for(int i=1;i*i<=n && !flag;i++)//枚举段数{if(n%i==0){flag|=solve(i,++cnt);flag|=solve(n/i,++cnt);}}if(flag) printf("Yes\n");else printf("No\n");}return 0;
}