补充上一版本的KMP只能兼容字符数字的情况
代码中有注解—不对的地方请指出共同学习
package com.test.autimatic;
/**
* KMP算法
* @author 25338
* @version 1.0
* @date 2021/12/22 21:37
*/
public class GpKmp {
public static void main(String[] args) {
System.out.println(kmp("abbabbabab","abbaba"));
}
/**
* 注:最长前缀和最长后缀匹配字符abbabb -》 最长前缀3-abb === 最长后缀3-abb
* ①.以aabsaasjbk为例
* ②.定义最长前后缀长度数组 int【】 kmp
* ③.kmp[0] =-1;kmp[1] = 0;固定
* ④.其他以注中求值
* ⑤.
*/
public final static int kmp(String source,String target){
if(source == null || target == null || source.length() < target.length()){
return -1;
}
//记录source下标位置和target下标位置
int s = 0;
int t = 0;
//获取target中每个字符对应的最长前后缀相等的长度
int[] arrayKmp = getArrayKmp(target);
//循环遍历source
for (; s < source.length() && t < target.length();) {
String sStr = source.substring(s, s + 1);
String tStr = target.substring(t, t + 1);
//如果相等则继续
if(sStr.equals(tStr)){
t++;s++;
//说明到了0位置
}else if(arrayKmp[t] == -1){
s++;
//否则的话找到target中最长前后缀相等的位置
}else{
t = arrayKmp[t];
}
}
//如果找到位置则返回
return t == target.length() ? s - target.length() : -1;
}
/**
* 计算target中每个位置之前的kmp的前后缀最长相等数组
* @param target
* @return
*/
private static final int[] getArrayKmp(String target){
int[] kmp = new int[target.length()];
kmp[0] = -1;kmp[1] = 0;int index = 0;
for (int i = 2; i < target.length(); i++) {
//记录index位置
index = kmp[i - 1];
//判断前一个位置和前一个位置的前缀长度位置是否相等---相等加一,不相等继续
while (kmp[index] != -1 && !target.substring(index,index + 1).equals(target.substring(i - 1,i))){
index = kmp[index];
}
if(target.substring(index,index + 1).equals(target.substring(i - 1,i))){
kmp[i] = index + 1;
}
}
return kmp;
}
}