做法:找出每条字符串的最小循环节,长度如果能整除,则求最小循环节与ans的最小公倍数,否则求字符串长度与ans的最小公倍数。
最小循环节=len-next[len]。//如需添加,则添加的最小字符串长度为(len-next[len])-len%(len-next[len]);
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
const int mod=1e9+7;
ll qpow(ll base,ll power){
ll res=1;
while(power>0){
if(power&1) res=base*res;
power>>=1;
base=base*base;
}
return res;
}
const int N=2e2+5;
int a[N];
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
void sovle(){
int n;
cin >> n;
string s;
cin >> s;
for(int i=1;i<=n;i++){
cin >> a[i];
}
vector<bool>v(n+1);
ll ans=1;
for(int i=1;i<=n;i++){
if(v[i]) continue;
string p;
for(int j=i;!v[j];j=a[j]){
v[j]=1;
p+=s[j-1];
}
vector<int>next(n+1);
next[0]=-1;
int k=0,j=-1;
int len=p.length();
while(k<len){
if(j==-1||p[k]==p[j]) ++k,++j,next[k]=j;
else j=next[j];
}
if(len%(len-next[len])==0) ans=lcm(ans,(ll)(len-next[len]));
else ans=lcm(ans,(ll)len);
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin >> t;
//scanf("%d",&t);
while(t--){
sovle();
}
}