#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e6+10;
int p[N];
ll lcm(ll a,ll b){
return a*b/__gcd(a,b);
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
string s;
cin>>s;
ll ans=1;
for(int i=0;i<n;i++)cin>>p[i],p[i]--;//预处理减一下,与s下标形成映射
for(int i=0;i<s.size();i++)
{
vector<char>v;
for(int j=i;;j=p[j]){
v.push_back(s[j]);//将第i个元素会走的那条路存起来
if(p[j]==i)break;
}
int l=v.size();
int c=v.size();
for(int k=1;k<l;k++)//枚举这个元素走多少部可以回到本身,最少为1,最大为c
{
if(l%k==0) //如果可以分成k步走,那就判断一下是不是可以只走k部
{
bool flag=true;
for(int j=0;j<l-k;j++){//判断走了k部之后元素是否一一对应
if(v[j]!=v[j+k]){
flag=false;
break;
}
}
if(flag){//是的话就更新最小步数且结束
c=k;
break;
}
}
}
ans=lcm(ans,c);
//求最小公倍数,某个元素走它需要走得最小步数的的倍数,那么肯定能够再走回去,所以求所有数的最小公倍数
}
cout<<ans<<'\n';
}
}
F - Shifting String(最小公倍数的应用)
于 2022-06-11 16:00:11 首次发布