給你一個字符串,它是由某個字符串不斷自我鏈接造成的。 可是這個字符串是不肯定的,如今只想知道它的最短長度是多少。ios
第一行給出字符串的長度,\(1 < L \le 1,000,000\). 第二行給出一個字符串,全由小寫字母組成。數組
輸出最短的長度。spa
8 cabcabca
3
對於樣例,咱們能夠利用"abc"不斷自我鏈接獲得"abcabcabc",讀入的cabcabca,是它的子串。code
首先讓咱們來研究一下結果的含義。ip
不妨設結果爲串\(T\)。 則原串爲:字符串
咱們怎樣利用起KMP中的nxt數組呢?input
因爲\(T\)串是最小循環子串,因此能夠標出KMP中\(nxt[n]\)(n爲\(|A|\))爲:string
結果爲n-nxt[n]!可是爲何呢?io
若是T不是最小循環子串的話,nxt[n]一定還能夠再加長。模板
不然,\(nxt[n]\)若再往左邊擴展,不妨設增加的爲\(T2\),剩下的\(T1\),分兩種狀況討論。
將兩個串對齊可得:
若兩串匹配,則顯然可得\(T2\)是\(T1\)的前綴,即\(T1=T2+R\),且\(R\)也是\(T1\)的前綴,餘下的爲\(T2\),即\(T1=R+T2\),則顯然\(T1\)是比\(T\)更小的循環子串,與前設矛盾,
故兩串一定不匹配。
***
將兩個串對齊可得:
同理。
若兩串匹配,則顯然可得\(T1\)是\(T2\)的前綴,即\(T2=T1+R\),且\(R\)也是\(T2\)的前綴,餘下的爲\(T1\),即\(T2=R+T1\),則顯然\(T2\)是比\(T\)更小的循環子串,與前設矛盾,
故兩串一定不匹配。
這樣一來,咱們就證實了答案爲\(n-nxt[n]\)!
而後就能夠直接套KMP模板了。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int nxt[1000001],n; char a[1000001]; int main(){ scanf("%d%s",&n,a); int k=0; for(int i=2;i<=n;i++){ while(k&&a[k]!=a[i-1])k=nxt[k]; if(a[k]==a[i-1])k++; nxt[i]=k; } printf("%d\n",n-nxt[n]); }