Java KMP算法总结


KMP 算法:比BF算法更为高效,BF算法的时间复杂度是:O(mn)

m代表主串的长度,n 代表子串的长度。而KMP的话,时间复杂度就变为 O(m+n);

KMP 和 BF 唯一不同,KMP主串的i并不会回退,并且j也不会移动到0号位置。那么会退到哪里呢??

这时候,对应的 next 数组:-1,0,0,0,1,2 next[2] 对应的就是 c.
假定主串 S 子串 P:
P0...PK-1 = Px...Pj-1
则有:P0...PK-1 = Pj-k...Pj-1


假如每一次不成功,肯定会有对应的一个K值。那么如何保存这些值?怎么求这些值?那这就是
KMP 的精髓。在这里就会出现新的东西,那就是 next 数组;也就是用 next[j] = k;来表示,不同的 j 来对应一个 K 值,
这个K就是将来要移动的j要移动的位置。

K值求法:找到匹配成功部分的两个相等的真子串(不包含本身),一个以下标 0 开始,另一个以 j-1 下标结尾。

不管什么数据 next[0] = -1;next[1] = 0;

 

 

 

得到 next 数组:通过 next[i]的值,通过一系列转换得到 next[i+1]得值,那么我们就能够实现这部分。
怎么做?

首先假设:next[i] = k 成立,那么,就有这个式子成立:P0...Pk-1 = Px...Pi-1;

得到:P0...Pk-1 = Pi-k..Pi-1;

假设如果 Pk = Pi:    得到 P0...Pk = Pi-k..Pi;那这个就是 next[i+1] = k+1;

那么:Pk != Pi 呢?看这个例子:abcababcabc

 

package string;

public class KMPDemo {
    //得到next数组
    public static void getNext(int[]next,String sub){
        next[0]=-1;
        next[1]=0;
        int i=2;
        int k=0;
        
        while(i<sub.length()){  
             if(k==-1||sub.charAt(k)==sub.charAt(i-1)){//Pk==P(i-1)                
                next[i]=k+1;
                i++;
                k++;





}else{

 


                k=next[k];
            }
        }
    }
    public static int KMP(String str,String sub,int pos ){
        if(pos<0||pos>str.length()||sub.length()>str.length()){
            return -1;
        }
        //开始查找
        int i=pos;
        int j=0;
        int[]next=new int[sub.length()];
        getNext(next,sub);
        //遍历主串和子串
        while(i<str.length()&&j<sub.length()){
            //判断对应下表是否相同
            if(j==-1l||str.charAt(i)==sub.charAt(j)){
                i++;
                j++;
            }else{
                j=next[j];//j返回到next【j】处
            }
            
        }
        //那种情况说明了子串在主串的位置
        if(j>=sub.length()){//
            return i-j;//子串出现在主串上的某一位置
        }else{
            return -1;//子串不在主串上
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String str="abcabcdabcd";
        String sub="dab";
        int index=KMP(str,sub,0);
        System.out.println(index);
    }

}

 

posted on 2018-05-13 13:11  番茄疯了  阅读(224)  评论(0)    收藏  举报