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

来源:互联网 发布:视频大数据什么意思 编辑:程序博客网 时间:2024/06/05 18:25

编程题之——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));        }    }
原创粉丝点击