1. 程式人生 > >[KMP][BZOJ1355][Baltic2009]Radio Transmission

[KMP][BZOJ1355][Baltic2009]Radio Transmission

字符 直接 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