KMP
代码来源于灵茶山艾府
模式串自匹配
int[] calculateMaxMatchLengths(String pattern) {
//子字符串匹配最大长度结果集
int[] maxMatchLengths=new int[pattern.length()];
//当前子字符串匹配最大长度
int maxLength=0;
//遍历
for(int i=1;i<pattern.length();i++){
//maxlength代表当前匹配最大长度的下一个字符,与新加入的字符做对比
//,看是否相等,如果不相等,则比较i-2与当前加入字符2比较
//如果maxlength=0,说明此子字符串序列中没有匹配前后缀字符串,那么让新加入的字符作为后缀第一个与前缀第一个作比较
//如果相等,最大长度+1
while(maxLength!=0&&pattern.charAt(maxLength)!=pattern.charAt(i)){
//maxLength代表i-1的最大匹配长度,maxlength-1就是i-2的最大匹配长度,因为maxlength每次增加幅度都是1,
//所以减一代表上一个序列的结果
//迭代到上一个序列作比较,如果等于0直接比较第一个与最后一个,不然继续迭代
maxLength=maxMatchLengths[maxLength-1];
}
//如果相等,最大匹配长度+1,并存到结果集里
if(pattern.charAt(maxLength)==pattern.charAt(i))
maxLength++;
maxMatchLengths[i]=maxLength;
}
//循环结束,返回结果集
return maxMatchLengths;
}
查询位置
List<Integer> search(String text, String pattern) {
List<Integer> positions=new ArrayList<>();
int[] maxs=calculateMaxMatchLengths(pattern);
int count=0;
for(int i=0;i<text.length();i++){
while(count>0&&text.charAt(i)!=pattern.charAt(count)){
count=maxs[count-1];
}
if(text.charAt(i)==pattern.charAt(count))
count++;
if(count==pattern.length()){
positions.add(i-count+1);
count=maxs[count-1];
}
}
//记录匹配字符个数
//如果有不匹配的字符,匹配字符串移动匹配的子字符串的最大匹配长度
//字符匹配,个数加一
//个数等于匹配字符长度,说明找到字符串,将字符串起始位置加入结果集,匹配字符串
return positions;
}