字符串的一种基本操作是子字符串查找:给定一端长度为N的文本字符串text和一个长度为M(M<N)的模式字符串pattern,在文本字符串中查找和该模式字符串相同的子字符串。
在这互联网时代,字符串查找的需求在很多情景都需要,如在文本编辑器或浏览器查找某个单词、在通信内容中截取感兴趣的模式文本等等。
子字符串查找最简单的实现肯定是暴力查找:
public static int search(String text, String pattern) {
int N = text.length();
int M = pattern.length();
for (int i = 0; i < N-M; i++) {
int j;
for (j = 0; j < M; j++) {
if (text.charAt(i+j) != pattern.charAt(j))
break;
}
if (j == M) return i;
}
return -1;
}
可以看到,暴力查找的最坏时间复杂度为O(N*M),实际应用中往往文本字符串很长(成万上亿个字符),而模式字符串很短,这样暴力算法的时间复杂度是无法接受的。
为了改进查找时间,人们发明了很多字符串查找算法,而今天的主角KMP算法(D.E.Knuth,J.H.Morris和V.R.Pratt发明,简称KMP算法)就是其中的一种。
暴力查找之所以慢是因为它每次的匹配都是从头开始,并且抛弃了之前已经算好的结果,KMP算法就是从这入手: 匹配失败后,已知晓的一部分文本字符串的内容信息,再利用这些内