数据结构与算法(二十)——KMP算法

概述

  1. KMP是一个解决模式串在文本串中是否出现过,如果出现过,获得最早出现的位置的经典算法(实现Java中的indexOf的功能)
  2. KMP算法利用遍历文本串时判断过的信息,通过一个next数组,保存模式串前后最长公共子序列的长度,每次回溯时,通过next数组找到前面匹配过的位置,省去了大量的计算时间

部分匹配值

部分匹配值就是前缀和后缀的最长共有元素长度
前缀:除了整个字符串以外,从头开始依次增加一个字符,如ABC的前缀表:{A,AB}
后缀:除了整个字符串意外,从尾开始依次增加一个字符,如ABC的后缀表:{C,BC}

部分匹配值的求解

	/**
	 * 获取部分匹配值表
	 * @param s 
	 * @return
	 */
	private static int[] kmpNext(String s) {
		int []next = new int[s.length()];
		// 在字符串长度为1的地方,前缀和后缀都是""所以,部分匹配值为0
		next[0] = 0;
		// 动态规划,已经初始化了长度为1的字符串的部分匹配值,从长度为2开始匹配
		for(int i=1,j=0;i<s.length();i++) {
			// 如果当前扫描到的字符和上次匹配的最后一个字符不同,返回上一次的部分匹配值
			while(j>0&&s.charAt(i)!=s.charAt(j)) {
				j = next[j-1];
			}
			// 如果扫描到的字符和上次匹配到的最后一个字符相同,则已经找到了最大公共长度
			// 因为最长的长度建立在短的基础上,短的依次累加到的满足当前条件的最大值就是最长公共长度
			if(s.charAt(i)==s.charAt(j)) {
				j++;
			}
			next[i] = j;
		}
		return next;
	}

KMP搜索算法

	/**
	 * kmp搜索
	 * @param s1 源字符串
	 * @param s2 子串
	 * @param next 子串的部分匹配表
	 * @return
	 */
	private static int kmpSearch(String s1,String s2,int []next) {
		for(int i=0,j=0;i<s1.length();i++) {
			// j不从0开始重新匹配,而是从前一个最长公共长度开始
			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;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值