编程题之——KMP算法Java实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013293125/article/details/77802971

编程题之——KMP算法Java实现

有如下问题:有模式字符串mode=”acabaabaabcacaabc”,有个目标字符串target=”abaabcac”,现在要在遍历mode串,看target串是否是目标串的子串。下面用KMP(模式匹配算法)实现。在KMP中,最主要的元素就是next[]数组的实现了。

一、next[]数组实现

声明:本方法参考了《数据结构(c语言版)》的KMP算法以及网上的一些KMP算法,解题过程与《数据结构(c语言版)》的KMP算法略有不同

1、next值求解过程

如果target串中,前缀等于后缀,即:“ p1p2.....pk1 ”=” pjk+1.....pj1 ”,则next[j]=k;又1< k< j(j>=1);next取值条件如下:
这里写图片描述

所以j=1时,next[0] = 0;当j=2时,属于其他情况,next[1]=1

当j=3时,j-1=2,串长为“ab”,则前缀取到k-1,后缀取到j-1:

k-1 前缀 关系 后缀
1 a != b

属于“其他情况”,所以next[3] = 1;

当j=4时,j-1=3,串长为“aba”,则前缀取到k-1,后缀取到j-1:

k-1 前缀 关系 后缀
1 a == a
2 ab != ba

在上表有前缀等于后缀的情况k-1=1,且没有其他前缀等于后缀时k值大于它的情况,所以k-1=1 =>k=2;next[4]=2;

当j=5时,j-1=4,串长为“abaa”,则前缀取到k-1,后缀取到j-1:

k-1 前缀 关系 后缀
1 a == a
2 ab != aa
3 aba != baa

在上表有前缀等于后缀的情况k-1=1,且没有其他前缀等于后缀时k值大于它的情况,所以k-1=1 =>k=2;next[5]=2;

当j=6时,j-1=5,串长为“abaab”,则前缀取到k-1,后缀取到j-1:

k-1 前缀 关系 后缀
1 a != b
2 ab == ab
3 aba != aab
4 abaa != baab

在上表有前缀等于后缀的情况k-1=2,且没有其他前缀等于后缀时k值大于它的情况,所以k-1=2 =>k=3;next[6]=3;

当j=7时,j-1=6,串长为“abaabc”,则前缀取到k-1,后缀取到j-1:

k-1 前缀 关系 后缀
1 a != c
2 ab != bc
3 aba != abc
4 abaa != aabc
5 abaab != baabc

上述属于next取值的三种情况中的“其他情况”,所以next[7]=1;

当j=8时,j-1=7,串长为“abaabca”,则前缀取到k-1,后缀取到j-1:

k-1 前缀 关系 后缀
1 a == a
2 ab != ca
3 aba != bca
4 abaa != abca
5 abaab != aabca
6 abaabc != baabca

在上表有前缀等于后缀的情况k-1=1,且没有其他前缀等于后缀时k值大于它的情况,所以k-1=1 =>k=2;next[8]=2;

总上所得,j与next[j]对应表如下:

j 1 2 3 4 5 6 7 8
target a b a a b c a c
next[j] 0 1 1 2 2 3 1 2

代码实现求next值

public static void getNext(String str,int next[]){
        int j = 1;
        next[1] = 0;
        next[2] = 1;
        int max = 0;
        for(j=3;j<=str.length();j++){
            max = 0;
            for(int k=2;k<j;k++){
                if(str.substring(0, k-1).equals(str.substring(j-k, j-1))){
                    if(k>max)
                        max = k;
                }
            }
            if(max == 0)
                next[j]=1;
            else
                next[j] = max;
        }
    }

KMP函数为:

public static void kmp(String mode,String target,int[]next){
        int j = 1;
        int i;
        for(i=1;i<=mode.length()&&j<=target.length();){
            if(j==0){
                i++;
                j++;
            }else{
                if(mode.charAt(i-1)==target.charAt(j-1)){
                    i++;
                    j++;
                }else{
                    j = next[j];
                }
            }
        }
        if(j>target.length()){//输出匹配成功的子串
            System.out.println(mode.substring(i-j, i-1));
        }
    }

猜你喜欢

转载自blog.csdn.net/u013293125/article/details/77802971
今日推荐