模式匹配KMP算法(Java)

/********查找匹配字符串**********/
//最原始、复杂度最高的做法
//返回childstr在mumstr中第pos个字符之后的位置,如果不存在,则返回0
public int FindStr(String mumstr, String childstr, int pos)
{
	//省去参数有效性判断
	
	if((childstr.length() > mumstr.length()) || (pos >= mumstr.length()))
		return 0;
	
	char[] mumarr = mumstr.toCharArray();
	char[] childarr = childstr.toCharArray();
	int i = pos;
	int j = 0;
	
	while((i < mumarr.length) && ( j < childarr.length))
	{
		//如果匹配情况
		if( mumarr[i] == childarr[j])
		{
			++i;
			++j;
		}
		//如果不匹配,则从头开始匹配
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}
	
	//判断是否匹配成功,如果匹配成功,则跳出循环条件应该为 j = childarr.length情况
	if( j >= childarr.length)
	{
		return i - j;
	}
	return 0;
}

/**************KMP算法*****************/
//KMP算法主要思想在于比较指针不回溯,通过计算next[j],将匹配指针回溯到next[j]位置与i位置的主字符串进行比较

//next[j]计算函数
/*初始化next[1] = 0;(注意实现时要注意算法中str的位置与算法中位置的区别)
  且注意计算next[j]时,比较的是一直到j-1的字符串
  next[j]计算共分为两种情况:记next[j] = k; 
  1.str[j] = str[k],则next[j + 1] = next[j] + 1 = k + 1;
  2.若不等,则把比较想象成模式和主字符串都是childstr的模式匹配。则应该让str[j] 和str[next[k]]进行比较(这里记next[j] = k);
    1) 相等,则next[j + 1] = next[k] + 1 = k' + 1;
	2) 不相等,则继续令next[k] = k',将str[j]与str[k' + 1]作比较;
*/
private int[] getNext(String childstr)
{
	//参数初始化
	int length = childstr.length();
	char[] childarr = childstr.toCharArray();
	int next[] = new int[length];
	next[0] = -1;//标志位字符串初始位
	int i = 0;
	int j = -1;
	
	while ( i < length - 1)
	{
		if( i == 0 || j == -1 ||childarr[i] == childarr[j])//注意不能忘记j=-1的初始情况
		{
			next[++i] = ++j;
		}
		else
		{
			j = next[j]; 
		}
	}	
	return next;
}
/*******************KMP算法********************/
public int IndexKMP(String mumstr, String childstr, int pos)
{
	if((childstr.length() > mumstr.length()) || (pos >= mumstr.length()))
		return 0;
	
	char[] mumarr = mumstr.toCharArray();
	char[] childarr = childstr.toCharArray();
	int i = pos;
	int j = 0;
	int[] next = getNext(childstr);
	
	while ((i < mumarr.length)&&(j < childarr.length))
	{
		if(j == -1 || mumarr[i] == childarr[j])//注意还要加上j=-1的最初始化情况
		{
			++i;
			++j;
		}
		else
		{
			//i不变,j变为next[j]
			j = next[j];
		}
	}		
	
	if ( j >= childarr.length)
	{
		return i - j;
	}
	return 0;	
}

public static void main(String[] args) {
	StrMatch strMatch = new StrMatch();
	String aString = "ababccddefgabcdefghij";
	String bString = "ababccddefg";
	
	System.out.println(strMatch.IndexKMP(aString, bString, 3));

}


/********改进的nextval算法********/
/*当遇到      a  a  a  a  b  情况
     next[j]  0  1  2  3  4
    nextval[j]0  0  0  0  1
	
	即当比较到b时不等,回溯到next[4] = 3位置,比较a,仍不等则继续前移next[3] = 2;仍然是比较a,结果仍然是不等
	故希望能够直接回溯至第一个a位置;
	
	则改进算法中,next[j] = k; 若str[j] = str[k],则应和str[next[k]]进行比较,若str[j] = str[next[k]],则继续前移,
	直至str[j]与其不相等;则next[j] = next[k],直至不相等的初始情况

*/

private int[] nextval(String childstr)
{
	//参数初始化
	int length = childstr.length();
	char[] childarr = childstr.toCharArray();
	int next[] = new int[length];
	next[0] = -1;//标志位字符串初始位
	int i = 0;
	int j = -1;
	
	while ( i < length - 1)
	{
		if( i == 0 || j == -1 ||childarr[i] == childarr[j])//注意不能忘记j=-1的初始情况
		{
			++i;
			++j;
			//再多一层对相等元素的判断
			if(childarr[i] == childarr[j])//对应next[j] = next[k]情况
			{
				next[i] = next[j];
			}
			else
			{
				next[i] = j;
			}
		}
		else
		{
			j = next[j]; 
		}
	}	
	return next;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值