m = P.length let pi[m] pi[1] = 0 k = 0 for q = 2 to m while k > 0 && P[k+1] != P[q] k = pi[k] if P[k+1] == P[q] k = k + 1 pi[q] = k return pi
匹配伪代码
1 2 3 4 5 6 7 8 9 10 11 12
n = T.length m = P.length pi = computePrefixFunction(P) q = 0 for i = 1 to n // 扫描文本T while q > 0 && P[q+1] != T[i] q = pi[q] // 下一个文本不匹配 if P[q+1] == T[i] q = q + 1 // 下一个文本匹配 if q == m print i - m q = pi[q] // 匹配失败直接跳到下一个位置
voidkmpSearch(String pat, String txt){ int m = pat.length(); int n = txt.length();
// 前缀函数 int[] lps = newint[m]; // 模式索引 int j = 0;
// 构建前缀函数 computeLPSArray(pat, m, lps);
// 文本索引 int i = 0; while (i < n) { if (pat.charAt(j) == txt.charAt(i)) { j++; i++; } if (j == m) { System.out.println("Found pattern at index " + (i - j)); j = lps[j - 1]; } elseif (i < n && pat.charAt(j) != txt.charAt(i)) { // 匹配失败按照前缀函数移动模式指针 if (j != 0) { j = lps[j - 1]; } else { i = i + 1; } } } }
voidcomputeLPSArray(String pat, int m, int[] lps){ // 前一个最长前缀的值 int len = 0; int i = 1; // 第一个字符固定0 lps[0] = 0;
// 1 to m-1 while (i < m) { if (pat.charAt(i) == pat.charAt(len)) { // 匹配就加1 len++; lps[i] = len; i++; } else { // (pat[i] != pat[len]) if (len != 0) { len = lps[len - 1]; } else { // len == 0) lps[i] = len; i++; } } } }
publicstaticvoidmain(String args[]){ String txt = "ABABDABACDABABCABAB"; String pat = "ABABCABAB"; new KMPStringMatcher().kmpSearch(pat, txt); } }