字符串匹配问题:KMP匹配算法

基本思想

字符串匹配问题:在文本串中寻找是否有与模式串相同的子串
在字符串匹配时,暴力匹配忽略了如果模式串开头与中间有重复部分,在将模式串的后面的重复部分匹配后,无法继续匹配的话,此时将模式串开头实际上也已经被匹配了,可以直接从开头重复部分之后开始匹配

这里引入了一个部分匹配值表,每个与模式串的字符对应,表示与开头的字符有没有相同的,如果有,表的值就是相同字符的下一位,但只从开头开始对应
这样就使用了匹配失败的结果,从而减少了匹配次数

算法实现

public static int kmpSearch(String s1,String s2)
	{
		//获得部分匹配值表
		int[] next = kmpNext(s2); 
		
		//遍历
		//i是s1的角标,j是s2的角标
		for(int i = 0, j = 0; i < s1.length(); i++)
		{
			//i与j角标元素不等,将s2右移到重复位置
			while(j > 0 && s1.charAt(i) != s2.charAt(j) )
				j = next[j - 1];
			
			if(s1.charAt(i) == s2.charAt(j))
				j++;
			
			if(j == s2.length())
				return i- j + 1;
		}
		
		
		return -1;
	}
	
	//获取部分匹配值表
	private static int[] kmpNext(String s)
	{
		//初始化匹配值表
		int[] next = new int[s.length()];
		
		//第一个匹配值为0
		next[0] = 0;
		
		//i用来遍历所有字符,初始值为1与j不同,j表示其匹配表下标
		for(int i = 1, j = 0; i < next.length; i++)
		{
			//i角标与j角标元素不等,将
			while(j > 0 && s.charAt(i) != s.charAt(j) )
				j = next[j - 1];
			
			//i角标与j角标元素相等,对双方下一位进行判断
			if(s.charAt(i) == s.charAt(j) )
				j++;
			
			//赋予匹配值
			next[i] = j;

		}
		
		return next;
	}

测试

public static void main(String[] args) {

		String s1 = "BBC ABCDAB ABCDABCDABDE";
		String s2 = "ABCDABD";
		
		System.out.println(kmpSearch(s1, s2));

	}

结果为

15

算法是有效的

算法分析
设s1有n个字符,s2有m个字符

  • 匹配过程要遍历s1数组,时间复杂度为O(n)
  • next数组要遍历s2数组,时间复杂度为O(m)
  • 总时间复杂度为O(n+m)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值