kmp

kmp:str1.indexOf(str2);
检查字符串2是1的子序列,并返回匹配的第一个字符位置
相比暴力匹配(时间复杂度O(N*M)),KMP通过nexts数组来加速匹配的过程,时间复杂度O(N)

next数组(建立的一个加速指标)
对str2,即要检查的字符串求next数组
nexts数组:i之前的字符串(和i本身无关)的前缀和后缀最大的匹配字符长度(不能取得整体,因为整体肯定是一样的,没有意义)

示例:nexts[]
a a x a a a a x a a x
0 1 2 3 4 5 6 7 8 9 10
-1 0 1 0 1 2 2 2 i
nexts[0]=-1 人为规定的
nexts[1]=0 不能取得整体所以是0
nexts[2]=1 a
nexts[3]=?怎么求?
看i-1位置的值是否等于y=next[i-1] y位置的值,
如果相等则nexts[i]=next[i-1]+1;
否则的话y=next[y]
当y=0时,则next[i]=0


加速匹配过程:
str1 a a b a a b k............
str2 a a b a a b a
i 0 1 2 3 4 5 6
next -1 0 3
nexts数组的用法:在遇到无法匹配的字符位置i(记为y)时,将str2[nexts[y]]=str1[i]
如果还是无法匹配时,将y重置为y=nexts[y] ->nexts[y],当nexts[y]=-1时,str2[0]==str1[i+1]
通过这种方式来加速匹配的过程

  private static int getIndexOf(String str1,String str2){
        if(str1==null||str2==null||str2.length()<1||str1.length()< str2.length()){
            return -1;
        }
        int[] next=getNextArray(str2.toCharArray());
        char[] ch1=str1.toCharArray();
        char[] ch2=str2.toCharArray();
        int x=0;//str1开始匹配的位置
        int y=0;//str2开始匹配的位置
        while (x<ch1.length&&y<ch2.length){//如果y越界,说明匹配成功,如果x越界,说明匹配结束了
            if(ch1[x]==ch2[y]){
                x++;
                y++;
            }else if(next[y]==-1){//y=0
                //表示一通加速后,都没有匹配上,换个头重新开始匹配
                x++;
            }else{
                y=next[y];
            }
        }
        return y==ch2.length?x-y:-1;//如果y的长度等于str.length说明匹配成功,匹配开始位置为x-y
    }

    private static int[] getNextArray(char[] ms){
        //如长度为1
        if(ms.length==1){
            return new int[]{-1};
        }
        //申请next数组
        int[] next= new int[ms.length];
        //o 位置为-1 人为规定
        next[0]=-1;
        //1位置为0,因为都不能取整体
        next[1]=0;
        //从位置2开始考虑
        int i=2;
        int y=0;//当前是哪个字符和i-1在比较
        //处理位置没有越界

//        nexts[i]=?怎么求?
//        看i-1位置的值是否等于y=next[i-1] y位置的值,
//        如果相等则nexts[i]=next[i-1]+1;
//        否则的话y=next[y]
        while (i<next.length){
            if(ms[i-1]==ms[y]){
                next[i++]=++y;
            }else if(y>0){
                y=next[y];
            }else {
                next[i++]=0;
            }
        }
        return next;
    }

  

上一篇:Java 练习(获取两个字符串中最大相同子串)


下一篇:LeetCode(五)