KMP算法
KMP算法主要解决字符串匹配问题,时间复杂度可以达到O(N)
/**
* kmp算法
*
* 概念:
* 字符串中每个位置的指标:当前字符之前的字符,前缀和后缀的最长匹配长度
* 例:abcabck 则k位置的指标为3,前缀最长为abc,后缀最长为abc
*
* <p>
* 解决问题(字符串匹配问题):
* 两个字符串A、B,A字符串是否包含B字符串
* 两棵树A、B,B是否和A的某颗子树相同
*
* @CreateDate 2020/10/22 16:01
**/
public class Kmp {
/**
* 判断字符串str中,是否存在match字符串,
* 存在返回第一次匹配的开始位置,不存在返回-1
*
* @param str
* @param match
* @return
*/
public int getIndexOf(String str, String match) {
//如果str为空,或者match为空,或者match的长度>str的长度,则都不存在,返回-1
if (str == null || match == null || match.length() < 1 || match.length() > str.length()) {
return -1;
}
char[] strCharArray = str.toCharArray();
char[] matchCharArray = match.toCharArray();
//str 中当前比对到的位置
int x = 0;
//match 中当前比对到的位置
int y = 0;
//匹配字符串中,各个字符位置的指标数组
int[] next = getNextArry(matchCharArray);
while (x < str.length() && y < match.length()) {
//如果当前str[x]位置的字符与match[y]当前的字符相等,则x和y同时往前移动
if (strCharArray[x] == matchCharArray[y]) {
x++;
y++;
//如果当前match的位置已经到第一个位置,则代表str之前的所有位置都没有匹配的,str向后移动一个位置
} else if (y == 0) {
x++;
//否则,y到当前位置的指标位置
} else {
y = next[y];
}
}
//最后要么x越界,要么y越界,如果y的值等于match的长度,说明匹配成功,返回x-y即为匹配到的开始位置
return y == match.length() ? x - y : -1;
}
/**
* 获取匹配字符串中各个位置字符的指标
*
* @param match
* @return
*/
public int[] getNextArry(char[] match) {
if (match.length == 1) {
return new int[]{-1};
}
int[] next = new int[match.length];
//人为规定,第一个位置为-1,第二个位置为0
next[0] = -1;
next[1] = 0;
//当前计算的位置
int index = 2;
//cn 代表,cn位置的字符,是当前和i-1位置比较的字符
int cn = 0;
while (index < match.length) {
//如果index-1位置的值和当前cn所在位置的值相等,则index位置的值对应的标准为cn+1,跳出来的时候
if (match[index - 1] == match[cn]) {
//next[i] = cn + 1
//index++ 计算下一个位置的值
//cn++ 即将面对下一个位置index+1的值,需要用到cn+1
next[index++] = ++cn;
} else if (cn > 0) {
//比对不成功,cn > 0 代表cn还可以往前跳
cn = next[cn];
} else {
next[index++] = 0;
}
}
return next;
}
}