Poj1961 Poj2406 最短迴圈節
阿新 • • 發佈:2019-01-24
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"); } } }