[KMP][BZOJ1355][Baltic2009]Radio Transmission
阿新 • • 發佈:2018-07-28
字符 直接 water 矛盾 mar 由於 最小 情況 watermark
,
Description
給你一個字符串,它是由某個字符串不斷自我連接形成的。 但是這個字符串是不確定的,現在只想知道它的最短長度是多少。
Input
第一行給出字符串的長度,\(1 < L \le 1,000,000\). 第二行給出一個字符串,全由小寫字母組成。
Output
輸出最短的長度。
SampleInput
8
cabcabca
SampleOutput
3
Hint
對於樣例,我們可以利用"abc"不斷自我連接得到"abcabcabc",讀入的cabcabca,是它的子串。
***
首先讓我們來研究一下結果的含義。
不妨設結果為串\(T\)。 則原串為:
我們怎樣利用起KMP中的nxt數組呢?
由於\(T\)串是最小循環子串,所以可以標出KMP中\(nxt[n]\)(n為\(|A|\))為:
結果為n-nxt[n]!但是為什麽呢?
*
如果T不是最小循環子串的話,nxt[n]必定還可以再加長**。
否則,\(nxt[n]\)若再往左邊擴展,不妨設增長的為\(T2\),剩下的\(T1\),分兩種情況討論。
1.\(|T1|>=|T2|\)
將兩個串對齊可得:
若兩串匹配,則顯然可得\(T2\)是\(T1\)的前綴,即\(T1=T2+R\),且\(R\)也是\(T1\)的前綴,余下的為\(T2\),即\(T1=R+T2\),則顯然\(T1\)是比\(T\)更小的循環子串,與前設矛盾
故兩串必定不匹配。
2.\(|T1|<|T2|\)
將兩個串對齊可得:
同理。
若兩串匹配,則顯然可得\(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]); }
[KMP][BZOJ1355][Baltic2009]Radio Transmission