// KMP算法
public class KMP {
int[] next;
String pattern;
String target;
KMP(String target, String pattern) {
this.pattern = pattern;
this.target = target;
this.next = new int[this.pattern.length()];
}
// 构造时,将后缀当作一个子串
public void createNext() {
int j = 0;
int i = 1;
this.next[0] = 0;
if (pattern.length() >= 2) // 至少有两个字符才能比较前缀和后缀
{
while (i < pattern.length())
{
if (pattern.charAt(i) == pattern.charAt(j)) // i和j指向的位置字符相同
{
next[i] = j+1; // j+1 表示相同的字符个数
i++;
j++;
}
else if (j > 0) // i和j指向的位置字符不同,且是中间位置不同,查找可行的位置
j = next[j-1];
else if (j == 0) // 没有找到前缀,更新到下一个后缀字符的位置
{
next[i] = 0;
i++;
}
}
}
}
public void showNext() {
for (int i = 0; i < this.next.length; i++)
System.out.print(this.next[i]);
}
public int findStr() {
int i = 0; // 标识主串的位置
int j = 0; // 标识模式串的位置
int ret = -1;
int rem = 0;
while (i < target.length() && j < pattern.length())
{
rem = i - j; // 记录起始位置
if (target.charAt(i) == pattern.charAt(j)) // i和j指向的位置字符相同
{
i++;
j++;
}
else if (j > 0) // i和j指向的位置字符不同,且是中间位置不同,查找可行的位置
j = next[j-1];
else if (j == 0)
i++;
}
if (j == pattern.length())
ret = rem;
return ret;
}
public static void main(String[] args) {
KMP k = new KMP("abcaabaaab", "aabaaab");
k.createNext();
k.showNext();
System.out.println();
System.out.println(k.findStr());
}
}
其中,next数组的构造过程参见答案提供的思路
事实上,构造Next数组的过程和查找子串的过程完全相同。