POJ1961:
先是用KMP“预处理"得出pre(程序中我习惯用p数组)。
那么关键就在于 (i+1)%(i-pre[i]) ==0 出现循环的判断上。怎么理解呢?这是就把数组 str 分成 (i+1) / (i-pre[i]) 个部分,由pre性质可以看出 这些部分全部相等 ,也就是最小循环节,不太清楚可以在数轴上画几笔即可。这就是本题的关键所在。
#include "stdio.h"
int p[1000010],N;
char str[1000010];
void get_p(int n)
{
int i,j=-1;
p[0]=-1;
for(i=1;i<n;i++)
{
while(j>-1 && str[i]!=str[j+1]) j=p[j];
if(str[i] == str[j+1]) j++;
p[i]=j;
}
}
int main()
{
int i,j,cas=1;
while(scanf("%d",&N),N)
{
scanf("%s",str);
get_p(N);
printf("Test case #%d\n",cas++);
for(i=1;i<N;i++)
{
if(p[i]!=-1 && (i+1)%(i-p[i])==0)
printf("%d %d\n",i+1,(i+1)/(i-p[i]));
}
printf("\n");
}
}
Poj2406 大同小异
#include "stdio.h"
#include "string.h"
int ans;
int p[1000010];
char str[1000010];
void get_p(int n)
{
int i,j=-1;
p[0]=-1;
for(i=1;i<n;i++)
{
while(j>-1 && str[i]!=str[j+1]) j=p[j];
if(str[i] == str[j+1]) j++;
p[i]=j;
}
}
int main()
{
int i,j,k,N;
while(1)
{
scanf("%s",str);
N=strlen(str);
if(N==1 && str[0]=='.') break;
get_p(N);
ans=1;
if(N==1) printf("1\n");
else{
if(N%(N-1-p[N-1])==0) printf("%d\n",N/(N-1-p[N-1]));
else printf("1\n");
}
}
}