• KMP 算法


    字符串匹配算法,一种是朴素算法,即字符串S与匹配字符串P从0开始逐个匹配,失配后右移一位从新匹配。

    另一种更高效的算法即是KMP算法。

    例如:S[0,n],P[0 ,m]

    如果S[ i ] != P[ j ]; 此时必有 式A:S[ i-j, i-1 ] = P[ 0 , j-1 ]  , 如果使用朴素算法则从S[ i-j+1] 开始与 P重新逐个匹配(即比较S[ i-j+1 ,i-j+1+m] 、P[0, m ]),这样时间复杂度为O(n*m),效率低。

    若我们保持S索引不变(即先考虑索引 i 之前的部分)上述比较等价于 式B:S[ i-j+1 , i-1] =? P[ 0, j-2 ];式B对于式A来看,假如我们将S看成不动,则P相对S右移了一位。

    在此假设 P右移K位,

    1)、有 式C S[ i-j+k , i-1] = P[ 0 , j-k-1] ( 0<k<=j-1);同时由式A 得 式D S[ i-j+k , i-1] = P[  k, j-1 ]   (k < =j-1), A中 j-1位相等,后k位也相等;

        由 C 、D 可得  E:P[0 , j-k-1] = P[ k , j-1] ;故可得 P[ 0 , j-1] 子串的前缀=后缀。(前面j-k 个等于 后面 j-k个)

        令 next = j-k;由上述可得其只与P[ 0 ,j-i] 有关,而与S无关;

        故假如我们求出各P[ 0, j ] ( 0<=j <=m)对应的 next值,即我们需要得到一个Next[m+1] 数组保存对应的next值;则当在任意位置失配时我们可以得到对应的右移值 k = j-next;

    2)、否则比较 S[ i ] 、P[ 0 ];

    Next数组的求法:

    假设 next[ j ] = t         ==>        P[ 0 , t-1]= P[ j-t+1 ,j]     ------  F;

    如果 P[ t ] = P[ j+1 ]   ==>         next[ j+1] = t +1 = next[ j ] +1 -------G;

    如果 P[ t ] != P[ j+1 ]  ,此时不能通过 next[ j ] 推导 next[ j+1 ],需要另行计算;

    //假如P[ 0 , v-1] = P[ j-v+1 , j ] ( v < t)------------I;

    //由 I、F得 P[ 0 , v-1] = P[ t-v , t-1] ( 因为 I中的两项分别为F中两项的子集) == 》 next[t-1] = v ---------------J

    //若P[ v ]  = P[ j+1] 则 next[ j+1 ] = v + 1 = next[t-1] +1  ,否则继续循环。

    换一种说法:

    因next[ t ] = v (t <j , 故已经求得 ),则 P[ 0 , v-1] = P[ t-v+1 , t] = P[ j-v+1 , j]

    如果 P[ v ]  = P[ j+1] 则 next[ j+1 ] = v + 1 否则继续循环

    next 实例算法:

    public static int[] getNext(char[] p)
        {
            if(p == null || p.length == 0)return null;
            int len = p.length;
            
            int i = 0 , j=-1;
            int[] next = new int[len];
            next[i] = -1;
            
            while(i<len-1)
            {
                if(j== -1 || p[i] == p[j])
                {
                    ++i;
                    ++j;
                    
                    if(p[i] != p[j])
                    {//因为p[i] != p[next[i]](如果相等,移动后p[next[i]] == p[i] == s[index] 和原来一样失配)
                        
                        next[i] = j;
                        
                    }
                    else
                    {//猜测如果
                        
                        next[i] = next[j];
                        
                    }
                }
                else
                {//如果不相等,需要在前j个字符中获取最长的前缀=后缀的子串
                    
                    j = next[j];//新的j值,表示p[0,j) ==p[i-j,i)
                    
                }
                
                SortHelper.showArray(next);
            }        
            return next;
        }

    kmp 算法

    public static int kmpSearch(char[] s , char[] p)
        {
            if(s== null || p== null)
            {
                return -1;
            }
            int sLen = s.length;
            int pLen = p.length;
            
            if(sLen <pLen)
            {
                return -1;
            }
            
            int[] next = getNext(p);
            
            int j=0;
            for(int i=0 ; i<sLen ;)
            {
                if(s[i] == p[j])
                {
                    if(j== pLen -1)
                    {
                        return i-j;
                    }
                    
                    i++;
                    j++;
                }
                else
                {
                    j = next[j];
                    if(j==-1)
                    {
                        i++;
                        j++;
                    }
                }            
            }
            
            return -1;
            
        }

    参考链接:

    http://blog.csdn.net/v_july_v/article/details/7041827

  • 相关阅读:
    Vue项目问题-TypeError: this.getOptions is not a function
    JavaScript学习-JavaScript 如何工作:对引擎、运行时、调用堆栈的概述
    JavaScript学习-理解JavaScript中的执行上下文和执行栈
    Element-ui中的给el-row添加一个gutter间隔不生效
    Vue-cil3 配置路径别名详解
    常见的内存泄漏以及解决方案
    Vue学习-组件之间的8种通信方式
    JavaScript学习-WeakMap和Map的区别,WeakMap的原理,为什么能被GC?
    Javascript学习-WeakMap
    JavaScript学习-Map
  • 原文地址:https://www.cnblogs.com/lipeil/p/2795686.html
Copyright © 2020-2023  润新知