#P5638. period题解
题目描述
给定一个长度为 NN 的字符串 SS,其中 2≤N≤1062≤N≤106。
定义 Pi=S[1..i]Pi=S[1..i],即字符串 SS 的前 ii 个字符组成的前缀。对于某些 PiPi,如果它可以表示为某个字符串重复 KK 次(K>1K>1 且 KK 尽可能大)的形式,则输出对应的 ii 和 KK。
输入格式
多组测试数据。
每组数据第一行包含一个整数,表示字符串的长度 NN。第二行包含一个长度为 NN 的字符串 SS。
输入以 00 表示结束。
输出格式
对于每组测试数据,首先输出一行 Test case #X,其中 XX 表示当前是第几组测试数据(从 11 开始编号)。然后按顺序输出所有满足条件的 ii 和 KK,每对 ii 和 KK 占一行。
输入数据 1
3
aaa
12
aabaabaabaab
0
输出数据 1
Test case #1
2 2
3 3
Test case #2
2 2
6 2
9 3
12 4
解释:
-
对于第一组数据,字符串为
aaa:- 前缀 P2="aa"P2="aa" 可以表示为 "a""a" 重复 22 次;
- 前缀 P3="aaa"P3="aaa" 可以表示为 "a""a" 重复 33 次。
-
对于第二组数据,字符串为
aabaabaabaab:- 前缀 P2="aa"P2="aa" 可以表示为 "a""a" 重复 22 次;
- 前缀 P6="aabaab"P6="aabaab" 可以表示为 "aab""aab" 重复 22 次;
- 前缀 P9="aabaabaab"P9="aabaabaab" 可以表示为 "aab""aab" 重复 33 次;
- 前缀 P12="aabaabaabaab"P12="aabaabaabaab" 可以表示为 "aab""aab" 重复 44 次。
思路
kmp
代码见下
#include<bits/stdc++.h>
using namespace std;
long long t,kmp[10000006],as,bs,op=0,db=0,w=0;
char a[10000006],b[10000006];
int main(){
while(cin>>t){
if(t==0){
break;
}
cin>>b+1;
db=1;
bs=strlen(b+1);
w++;
cout<<"Test case #"<<w<<endl;
for(int i=2,j=0;i<=bs;i++){
while(j!=0&&b[i]!=b[j+1]){
j=kmp[j];
}
if(b[j+1]==b[i]){
j++;
}
kmp[i]=j;
}
for(int i=0;i<=bs;i++){
b[i]=' ';
}
for(int i=2;i<=bs;i++){
if(i%(i-kmp[i])==0&&i/(i-kmp[i])>=2){
cout<<i<<" "<<i/(i-kmp[i])<<endl;
}
}
}
return 0;
}

浙公网安备 33010602011771号