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

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

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

一、next[]数组实现

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

1、next值求解过程

如果target串中,前缀等于后缀,即:“$p_1p_2.....p_{k-1}$”="$p_{j-k+1}.....p_{j-1}$",则next[j]=k;又1< k< j(j>=1);next取值条件如下: ![这里写图片描述](https://img-blog.csdn.net/20170902181335294?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzI5MzEyNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

所以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));
		}
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值