/**
* 字符串工具类
*/
public class StringUtils {
/**
* 使用KMP算法获取指定字符串在目标字符串中最小的位置下标
* <p>
* 算法时间复杂度:O(n+m) <br/>
* 例:str="abccbaabc", ptr="abc", result=0 <br/>
* String的indexOf是暴力匹配,时间复杂度为O(n*m),某些情况下效率不会很高
* </p>
*
* @see String#indexOf(String)
* @param str 目标字符串
* @param ptr 指定字符串
* @return -1表示未找到
*/
public static int indexOfByKMP(String str, String ptr) {
if (str == null || ptr == null){
return -1;
}
int sLen = str.length();
int pLen = ptr.length();
if (ptr.length() == 0) {
return 0;
}
// 记录当前长度的字符串的最大前后缀长度,下标为0表示当前字符串长度为1
int[] next = new int[pLen];
// -1表示不存在相同的最大前缀和最大后缀
next[0] = -1;
// k记录当前匹配到的前后缀的长度
int k = -1;
// 将ptr字符串的对应子串的前后缀长度保存到next数组中
for (int i = 1; i < pLen; i++) {
// 如果下一个字符不匹配,那么k就变成next[k]
while (k != -1 && ptr.charAt(k + 1) != ptr.charAt(i)) {
// 往前回溯,next[k]始终<=k
k = next[k];
}
if (ptr.charAt(k + 1) == ptr.charAt(i)) {
k++;
}
// 获取当前子串的最大前后缀长度
next[i] = k;
}
k = next[0];
//
for (int i = 0; i < sLen; i++) {
while (k != -1 && str.charAt(i) != ptr.charAt(k + 1)) {
// 回溯找到能匹配的最大前后缀和
k = next[k];
}
if (str.charAt(i) == ptr.charAt(k + 1)) {
k++;
}
// 完全匹配,返回结果
if (k == pLen - 1) {
return i - pLen + 1;
}
}
return -1;
}
}
根据KMP算法实现String的indexOf方法
最新推荐文章于 2024-09-18 20:33:32 发布