zoukankan      html  css  js  c++  java
  • KMP

    KMP学了好几遍了,今天才明白的差不多...

    留篇博客,免得自己以后忘了qaq

    我们先讨论next的含义:

    next[i] : 在0<=j<i中的最大的j,满足0-i中,使长度为j的后缀和长度为j的前缀相同

    接下来我们讨论两个问题:1.怎么求next; 2.有了next怎么求匹配

    定义:next[1] = 0(由定义),next[0]不定义,默认为0

    问题1:怎么求next

    考虑目前到i + 1,令j=next[i],那么如果a[j + 1] != a[i + 1],说明此时的next[i]的下一位与a[i + 1]不等,即next[i + 1] != next[i] + 1了

    那么和0-i的这一段后缀相等的最大前缀只能是next[j]即next[next[i]],那么令j=next[j],继续进行上述判断,直到j=0无法判断为止

    问题2:有了next怎么求匹配

    考虑目前匹配到模版串的j,原串的i,如果a[j] == a[i],自然这一位相等,令j++

    否则,已经匹配的一段j中,有一部分和原串之前匹配的部分是相等的,这个位置就是next[j](显然的由next的定义,这个长度是合法且极大的)

    这样问题就可以解决了

    考虑kmp的复杂度,在问题2中,我们至多只令j增加n次,而虽然在令j=next[j]的过程中可能有多次运算,但可以通过势能分析证明

    我们将j=next[j]的复杂度摊到每次j++,那么每次操作平均复杂度至多是2,总复杂度O(n+m)

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int maxn=1e7+1;
    int next[maxn],j=0;
    char s1[maxn],s2[maxn];
    int main()
    {
        scanf("%s",s1+1);
        scanf("%s",s2+1);
        int len1=strlen(s1+1),len2=strlen(s2+1);
        //cout<<len1<<" "<<len2;
        for(int i=2;i<=len2;i++)
        {
            while(j&&s2[i]!=s2[j+1]) j=next[j];
            if(s2[i]==s2[j+1]) j++;
            next[i]=j;
        }
        j=0;
        for(int i=1;i<=len1;i++)
        {
            while(j&&s1[i]!=s2[j+1]) j=next[j];
            if(s1[i]==s2[j+1]) j++;
            if(j==len2) 
            {
                printf("%d
    ",i-len2+1);
                j=next[j];
            }
            //cout<<"hahha"<<endl;
        }
        for(int i=1;i<=len2;i++) printf("%d ",next[i]);
    }
    View Code
  • 相关阅读:
    数字图像处理领域就业前景
    opencv 学习方法
    学习opencv tutorials
    win64+VS2010+OPENCV2.4.9配置问题
    libsvm使用步骤
    生成libSVM的数据格式及使用方法
    一堆应该记住的概念
    static静态变量的理解
    C程第一节课
    扫雷但是不会恭喜
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10801925.html
Copyright © 2011-2022 走看看