【BZOJ1355】【Baltic2009】Radio Transmission 详细证明【KMP】

Description

【题目描述】

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

【输入】

  第一行给出字符串的长度,1 < L ≤ 1,000,000. 第二行给出一个字符串,全由小写字母组成.

【输出】

  输出最短的长度
  
题解
首先,我们对这个字符串求一遍 next n e x t 数组, next[i] n e x t [ i ] 表示i的前缀和后缀的最长的相同的长度,即最长前缀后缀。答案就是 nnext[n] n − n e x t [ n ] 。但是为什么呢?
证明
不妨设文本串为T, n=|T| n = | T |
这里写图片描述
下面我要证明 Tnext[n] T − n e x t [ n ] 一定是字符串的循环节。
我们把 next[n] n e x t [ n ] T T 这两个字符串对齐。
这里写图片描述
此时相同位置的字符是相同的。
这里写图片描述
显然,标红位置,即Tnext[n] next[n] n e x t [ n ] 的开头是相同的。
这里写图片描述
再可以把 next[n] n e x t [ n ] 的标红部分对应回 T T 上面,又对应到next[n]上面。
这里写图片描述
我们可以像这样把 T T next[n] Tnext[n] T − n e x t [ n ] 填充满,所以 Tnext[n] T − n e x t [ n ] 一定是字符串的循环节。
那为什么 Tnext[n] T − n e x t [ n ] 一定是最短的呢?
因为如果存在比 Tnext[n] T − n e x t [ n ] 更短的循环节,根据 next n e x t 数组的定义, next[n] n e x t [ n ] 一定会加长。所以不存在比 Tnext[n] T − n e x t [ n ] 更短的循环节。
因此 Tnext[n] T − n e x t [ n ] 一定是T的最短循环节, nnext[n] n − n e x t [ n ] 就是这个循环节的长度。
代码:

#include<cstdio>
int n,next[1000005];
char s[1000005];
int main(){
    scanf("%d%s",&n,s);
    next[0]=next[1]=0;
    for(int i=1;i<n;i++){
        int j=next[i];
        while(j&&s[i]!=s[j]){
            j=next[j];
        }
        next[i+1]=s[i]==s[j]?j+1:0;
    }
    printf("%d\n",n-next[n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值