KMP算法

题目描述

【题目】

给定两个字符串str和match,长度分别为N和M。实现一个算法,如果字符串str中含有字串match,则返回match在str中的开始位置,不含有则返回-1。

【举例】

str=“acbc”,match=“bc”。返回2。

str=“acbc”,match=“bcc”。返回-1。

【要求】

如果match的长度大于str长度(M>N),str必然不会含有match,可直接返回-1。但如果N>=M,要求算法复杂度O(N)。

题目分析

字符串匹配的KMP算法,简单易懂。

经典算法题精讲(五)-Manacher算法、bfprt算法、KMP算法(下),讲的很详细。

代码实现

// Java 实现
public int KMPSearch(String s, String m) {
	if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
		return -1;
	}
	char[] ss = s.toCharArray();
	char[] ms = m.toCharArray();
	int si = 0;
	int mi = 0;
	int[] next = getNextArray(ms); // next数组考虑的是除当前字符外的最长相同前缀后缀
	while (si < ss.length && mi < ms.length) {
		if (ss[si] == ms[mi]) {
			si++;
			mi++;
		}
		else if (next[mi] == -1) {
			si++;
		}
		else { // 如模式串中在mi处的字符跟文本串在si处的字符匹配失配时
			mi = next[mi]; // 下一步用next[mi]处的字符继续跟文本串si处的字符匹配
						   // 相当于模式串向右移动 mi - next[mi] 位
		}
	}
	return mi == ms.length ? si - mi : -1;
}


// ***cn-----***pos-1pos
public int[] getNextArray(char[] ms) {
	if (ms.length == 1) {
		return new int[] { -1 };
	}
	int[] next = new int[ms.length];
	next[0] = -1;
	next[1] = 0;
	int pos = 2;
	int cn = 0;
	while (pos < next.length) {
		if (ms[pos - 1] == ms[cn]) {
			// next[pos++] = ++cn;
			next[pos] = next[pos-1] + 1;
			pos++;
			cn++;
		}
		else if (cn > 0) {
			cn = next[cn];
		}
		else {
			next[pos++] = 0;
		}
	}
	return next;
}
posted @ 2015-09-13 11:29  枯桃  阅读(177)  评论(0编辑  收藏  举报