给你一个字符串,它是由某个字符串不断自我链接造成的。 可是这个字符串是不肯定的,如今只想知道它的最短长度是多少。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]); }