这道题可以想到用KMP来解决,根据定义,对于每一个i,S[1-Nxt[i]+1~i]=S[1~Nxt[i]],并且不存在更大的循环节
Nxt[i]数组表示以i结尾的非前缀串与自身的前缀能匹配的最大数,可以方便更新
主要性质:
- 必要性:若循环元为len,当且仅S[1~i-len]=S[len+1~i]
- 充分性:从S[1~i-len]与S[len+1~i]各取len个字符,则S[1~len]=S[len+1~2*len],并以此类推,可以得出循环节的结论
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int nxt[N],n,cnt;
char a[N];
inline void pre(){
nxt[1]=0;
for(int i=2,j=0;i<=n;i++){
while(j>0&&a[i]!=a[j+1])j=nxt[j];//不断寻找能够继续匹配的
if(a[i]==a[j+1])++j;//继续更新
nxt[i]=j;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%s",&n, a+1);
pre();
printf("Test case #%d\n",++cnt);
for(int i=1;i<=n;i++)
if(i%(i-nxt[i])==0&&i/(i-nxt[i])>1)//注意特判要大于1的循环次数
printf("%d %d\n",i,i/(i-nxt[i]));
puts("");
}
}