1. 程式人生 > >【POJ】1961 Period-KMP

【POJ】1961 Period-KMP

傳送門:poj

題意

給定一個長度為n的字串S,求它每個字首的最短迴圈節。

題解

運用kmp判迴圈串: 對於位置ii,若i%(inxti)=0i\%(i-nxt_i)=0,則存在迴圈節,迴圈節長度為iinxti\dfrac{i}{ i-nxt_i} 證明: 在這裡插入圖片描述如圖: 設字串S1,S2,S3,S4,S5,S6S_1,S_2,S_3,S_4,S_5,S_6 由kmp性質顯然 S1=S4,S2=S5,S3=S6S_1=S_4,S_2=S_5,S_3=S_6 同時 S

2=S4,S3=S5S_2=S_4,S_3=S_5 所以S1S_1~S6S_6全部相等,且SiS_i為字首ii的最短迴圈節。(若有更短的迴圈節,nxtinxt_i必然更大)

程式碼

#include<cstdio>
using namespace std;
const int N=1e6+10;
int n,nxt[N],kmp,TK;
char s[N];

int main(){
	int i;
	for(;;){
		scanf("%d",&n);
		if(!n) break;
		scanf("%s",s+1);
		kmp=0;
		if(TK) puts("");
		printf("Test case #%d\n",++TK);
		for(i=2;i<=n;++i){
			for(;kmp && s[kmp+1]!=s[i];kmp=nxt[kmp]);
			kmp+=(s[kmp+1]==s[i]);
			nxt[i]=kmp;
			if(nxt[i]>0 && (i%(i-nxt[i]))==0) 
			 printf("%d %d\n",i,i/(i-nxt[i]));
		}
	}
	return 0;
}