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


    Description

    【题目描述】

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

    【输入】

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

    【输出】

      输出最短的长度
      
    题解
    首先,我们对这个字符串求一遍next数组,next[i]表示i的前缀和后缀的最长的相同的长度,即最长前缀后缀。答案就是nnext[n]。但是为什么呢?
    证明
    不妨设文本串为T,n=|T|
    这里写图片描述
    下面我要证明Tnext[n]一定是字符串的循环节。
    我们把next[n]T这两个字符串对齐。
    这里写图片描述
    此时相同位置的字符是相同的。
    这里写图片描述
    显然,标红位置,即Tnext[n]next[n]的开头是相同的。
    这里写图片描述
    再可以把next[n]的标红部分对应回T上面,又对应到next[n]上面。
    这里写图片描述
    我们可以像这样把Tnext[n]Tnext[n]填充满,所以Tnext[n]一定是字符串的循环节。
    那为什么Tnext[n]一定是最短的呢?
    因为如果存在比Tnext[n]更短的循环节,根据next数组的定义,next[n]一定会加长。所以不存在比Tnext[n]更短的循环节。
    因此Tnext[n]一定是T的最短循环节,nnext[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-next[n]);
        return 0;
    }
  • 相关阅读:
    python依赖包整体迁移方法
    ubuntu关于ssh协议登录问题
    k8s部署02-----kubeadm部署k8s
    k8s部署01-----what is k8s?
    兼容到ie10的js文件导出、下载到本地
    webstorm减少内存占用
    foxmail占cpu 100%解决办法
    原生js返回顶部
    js字符串驼峰和下划线互相转换
    element-ui的rules中正则表达式
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476898.html
Copyright © 2020-2023  润新知