KMP算法
KMP算法主要维护了一个最长前后缀的表,当待匹配串和匹配串的指针一起向前退的时候,遇到不相等的字符,待匹配串不用再回到起始位置的下一个位置重新匹配(暴力匹配),只需要查表更改匹配串的匹配指针继续向下走即可,从而将n*m的复杂度降低为接近n的复杂度。
实际代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| interface IMatch{ int find(); } class BaoLi implements IMatch{ private String text; private String pattern;
public BaoLi(String text, String pattern) { this.text = text; this.pattern = pattern; }
@Override public int find() { int m = text.length(); int n = pattern.length(); int i = 0; while (i < m){ int start = i; int j = 0; while(text.charAt(i) == pattern.charAt(j)){ if(j == n-1) return start; i++; j++; } i = ++start; } return -1; } }
public class KMP implements IMatch{ private String text; private String pattern; private int[] prefixTable;
public KMP(String text, String pattern) { this.text = text; this.pattern = pattern; prefixTable = new int[pattern.length()]; createPrefixTable(); movePrefixTable(); }
@Override public int find() { int i = 0; int j = 0; int m = text.length(); int n = pattern.length(); while (i < m) { if (j == n - 1 && text.charAt(i) == pattern.charAt(j)) return i - n + 1; if (text.charAt(i) == pattern.charAt(j)) { i++; j++; } else { j = prefixTable[j]; if (j == -1) { i++; j++; } } } return -1; }
private void createPrefixTable() { prefixTable[0] = 0; int len = 0; int i = 1; while (i < pattern.length()) { if (pattern.charAt(i) == pattern.charAt(len)) { prefixTable[i++] = ++len; } else { if (len > 0) { len = prefixTable[len - 1]; } else { prefixTable[i] = len; i++; } } } }
private void movePrefixTable() { int i; for (i = prefixTable.length - 1; i > 0; i--) { prefixTable[i] = prefixTable[i - 1]; } prefixTable[0] = -1; }
public static void main(String[] args) { String s1 = "aaaaaaaaasastiii"; String s2 = "aaas"; IMatch match1 = new KMP(s1, s2); IMatch match2 = new BaoLi(s1,s2);
System.out.println(s1 + " " + s2 + " : " + match1.find());
System.out.println(s1 + " " + s2 + " : " + match2.find());
} }
|