解法:
其实用很普通的“自然溢出法的Hash”就可以过这道题目(ps:出题人真良心没有故意卡我的Hash)。首先我们先枚举字串的长度length_k,之后我们在找出每个长度为length_k的字串,用Hash判断一下这些字串是否相同就可以了。时间复杂度:
\[ O (n/1+n/2+n/3+\cdots+n/n)\approx O(n)\]
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+5;
const int Base = 31;
char s[N];
unsigned long long Hash[N];
unsigned long long power[N]; //power[i]=base^i;
int main(){
power[0]=1;
for(int i=1;i<N;i++) power[i]=power[i-1]*Base;
while(true){
scanf("%s",s);
if(s[0]=='.') break;
int length=strlen(s); //获取字符串的长度
Hash[0]=0;Hash[1]=(unsigned long long)s[0];
for(int i=2;i<=length;i++) Hash[i]=Hash[i-1]*Base+(unsigned long long)s[i-1]; //计算Hash值
for(int length_k=1;length_k<=length;length_k++){ //枚举可能匹配的长度
if(length%length_k!=0) continue;
unsigned long long t; //用于储存上一个k
bool flag=true;
for(int i=length_k;i<=length;i+=length_k){ //枚举起点
unsigned long long k=Hash[i]-Hash[i-length_k]*power[length_k];
if(i!=length_k){
if(t!=k){
flag=false;
break;
}
}
t=k;
}
if(flag){
printf("%d\n",length/length_k);
break;
}
}
}
return 0;
}