前面腾讯面试这题时,很多概念都搞混了,过来反省,好好研究了下KMP算法,把它实现。
大体过程数据结构上都说得很明白,
这里说说自己的感悟吧:
主要是next数组的作用:
现有一个主串s和模式串t,KMP算法会首先对模式串t求一个辅助数组next,有个这个next后我们每次匹配时主串的下标i就不用回溯,模式串的下标j回溯到next[j]的位置。
看似next值越大越好,其实不是这样,next值当然是为0,为-1时最好。这个next数值k的意思表示当si!=tj时,那么tj-ktj-k+1...tj-1和主串的s0s1..sk-1是匹配的,那么
其实需要回溯k位置,即主串回溯到i-k位置和t0比较。当然,由于这一串又相等了,我们可以认为i不需要回溯,j直接移到k位置来比较就好。这样宏观来看,就是模式串t滑动
了j-next[j]个位置,那么当时是next[j]越小时,滑动的距离就越多,效率就越高。
java实现如下:
View Code
private static int[] getNext(char[] s) { int len = s.length, j = 0, k = -1; int[] next = new int[len]; next[0] = k; while (j < len - 1) { if (k == -1 || s[j] == s[k]) { j++; k++; next[j] = k; } else k = next[k]; } return next; } private static int match(char[] oStr, char[] tStr) { int i = 0, j = -1; int[] next = getNext(tStr); for (int k : next) { System.out.print(k + ","); } while (i < oStr.length && j < tStr.length) { if (j == -1 || oStr[i] == tStr[j]) { i++; j++; } else j = next[j]; } if (j >= tStr.length) return i - j; else return -1; }