Transmission--bzoj1335(题解)

#题目描述


给你一个字符串,它是由某个字符串不断自我连接形成的。
但是这个字符串是不确定的,现在只想知道它的最短长度是多少.

这里写图片描述

#题解


这是一道结论题:$n-next[n]$
那么怎么证明呢??

我们把文本T与next[n] 取出来并且开头对齐,如图:
这里写图片描述
此时相同位置的字符是相同的。
因为题目告诉我们文本串是由一个某个字符串不断自我连接形成的。
那么$T-next[n]$和$next[n]$的开头是一样的
将所对应的回到文本T上去,在回到next上,这样反复对应,我们发现$T$和$next[n]$ 可以用$T-next[n]$ 填充满,所以$T-next[n]$一定是文本串的循环节。
那么如何证明$T-next[n]$是最短的循环节呢,我们回忆一下next数组的定义,如果存在比$T-next[n]$更短的循环节的话,next会更长,所以$T-next[n]$是最短的。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//By Bibi
/// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
/// __.' ~. .~ `.__
/// .'// \./ \\`.
/// .'// | \\`.
/// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
/// .'//.-" `-. | .-' "-.\\`.
/// .'//______.============-.. \ | / ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=1000010;
int len;
int next[MAXN];
int read(){
int sum=0,flag=1;
char c;
for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
return sum*flag;
}
int n;
char s[MAXN];
void init(){
n=read();
scanf("%s",s+1);
len=strlen(s+1);
}
void yuchuli(){
int j=0;
next[1]=0;
rep(i,2,len){
while(j&&s[i]!=s[j+1]) j=next[j];
if(s[i]==s[j+1]) ++j;
next[i]=j;
}
}
int main(){
init();
yuchuli();
printf("%d",n-next[n]);
return 0;
}