KMP算法
解决的问题:快速匹配两个相同结构的子串是否相等
假设字符串str长度为N,字符串match长度为M,M <= N
想确定str中是否有某个子串是等于match的。
可以通过KMP算法,使得时间复杂度O(N)
KMP算法核心
如何理解next数组
1)next数组定义:next[i]表示match字符串从0-(i-1)这个子串中,最长的“前缀子串与后缀子串相等”的长度。
2)next[0]=-1 next[1]=0
3)快速求解next数组:
如果next[i-1]位置的值为x,且match字符串中i位置的值与x位置的值相等,则next[i]=x+1。
如果next[i-1]位置的值为x,且match字符串中i位置的值与x位置的值不相等,则查看next[x]的值,假设其值为y;则比较match字符串中i位置的值与y位置的值,如果相等则next[i]=y+1,以此类推。
如何利用next数组加速匹配过程
1)因为next数组的值记录的是前面子串的最长前后缀子串相等的长度,则当字符串匹配到某一个字符不相等时,假设该位置的next[i]=x;则因为前后缀相子串的原因,match字符串中的0-(x-1)肯定也相等,就不需要比较,直接从match字符串的第x位置开始比较。这样将加速匹配过程
//匹配过程
public static int getIndexOf(String s1, String s2) {
if (s1 == null || s2 == null || s2.length() < 1 || s1.length() < s2.length()) {
return -1;
}
char[] str1 = s1.toCharArray();
char[] str2 = s2.toCharArray();
int x = 0;
int y = 0;
// O(M) m <= n
int[] next = getNextArray(str2);
// O(N)
while (x < str1.length && y < str2.length) {
if (str1[x] == str2[y]) {
x++;
y++;
} else if (next[y] == -1) { // y == 0
x++;
} else {
y = next[y];
}
}
return y == str2.length ? x - y : -1;
}
//求next数组过程
public static int[] getNextArray(char[] str2) {
if (str2.length == 1) {
return new int[] { -1 };
}
int[] next = new int[str2.length];
next[0] = -1;
next[1] = 0;
int i = 2; // 目前在哪个位置上求next数组的值
int cn = 0; // 当前是哪个位置的值再和i-1位置的字符比较
while (i < next.length) {
if (str2[i - 1] == str2[cn]) { // 配成功的时候
next[i++] = ++cn;
} else if (cn > 0) {
cn = next[cn];
} else {
next[i++] = 0;
}
}
return next;
}