zoukankan      html  css  js  c++  java
  • KMP算法学习

    KMP这个算法原理的学习已经搁置了一年了,现在下定决心搞懂它。因为比较难,所以特地开辟几篇博客来,以后绝对不能只套板子,要深刻理解原理。

    参考链接:http://blog.csdn.net/yutianzuijin/article/details/11954939/

    首先,我们的目标是在O串中寻找f。

    对于暴力匹配法,就是把f从O的开头开始匹配,遇到不匹配的就把f往后挪1位重新匹配。

    而对于kmp算法,遇到失配的情况,不仅仅要把f往后挪1位,而是要把f往后挪很多位。不仅如此,还不用重新匹配,而是继续匹配。

    下面这个图非常好,假设f串向后挪了k位。说明什么呢?说明A=B,A是f的前缀,B是失配位之前的后缀。

    我们如果令next[i]表示f[0..i-1]最长的相等的前缀和后缀(串本身除外),那么每次向后移动的这个k就等于i-next[i]。

    首先,这样挪之后,后面可以正常匹配是很显然的。那么问题是,这样挪,就不会漏掉中间的一些吗?被跳过的那些位就一定没有能匹配的吗?

    答案是没有。可以用反证法来证明。假设有一个位置t它能匹配。类似于下面这个图。

    我们发现,有一个更长的前缀和后缀相等了,与next[i]是最长的相等前缀后缀矛盾。因此中间漏掉的情况是不存在的。

    所以我们可以放心大胆的每次失配,f串向后移动i-next[i]位,然后继续匹配失配位。

    那么这里有一个问题,当匹配完整个f之后,下次该往哪走呢?(假如我们不仅仅满足于找到一个匹配位置,而是要找出所有匹配位置)

    其实这里只需要想:匹配完一个串以后,下次可能再匹配的位置在哪里呢?其实把f往后挪l-next[l],其中l是f串的长度。

    那么现在有一个问题了,上面说的把f往后挪i-next[i],实际上在编程实现的时候并不这样写。假设i是O的匹配指针,j是f的匹配指针,那么我们想把j往后挪j-next[j],其实就是j=next[j],下次继续让i和j匹配。

    下面是假设我们已经得到了next数组,来求f串在O串中出现的次数和位置的代码。

    int nxt[1000];
    vector<int> P;
    int KMP(char f[],int n,char O[],int m)
    {
        int cnt=0;
        P.clear();
        getnext(f,n,nxt);
        int nowi=0,nowj=0;
        while (nowi<m)
        {
            while (nowj!=-1 && O[nowi]!=f[nowj]) nowj=nxt[nowj];
            nowi++,nowj++;
            if (nowj==n)
            {
                cnt++;
                P.push_back(nowi-nowj);
                nowj=nxt[nowj];
            }
        }
        return cnt;
    }

    下面是另一个重要问题,怎么求next数组。

    void getnext(char x[],int m,int nxt[])
    {
        int i,j;
        j=nxt[0]=-1;
        i=0;
        while(i<m)
        {
            while(-1!=j && x[i]!=x[j])j=nxt[j];
            nxt[++i]=++j;
        }
    }
  • 相关阅读:
    微软职位内部推荐-Senior SDE
    在使用Fake framework的时候,为什么有一些函数没有生产mock呢?
    Call Azure Queue get "The remote server returned an error: (400) Bad Request."
    技术分享
    IT牛人博客
    Spring-data-redis操作redis cluster
    Spring对Hibernate事务管理【转】
    Hibernate事务管理
    Redis与Memcached对比
    LockSupport的park和unpark
  • 原文地址:https://www.cnblogs.com/acmsong/p/7265862.html
Copyright © 2011-2022 走看看