常见经典算法
KMP算法
参考:https://www.bilibili.com/video/BV1jb411V78H?from=search&seid=6567338116212695926
关键字:有效回溯、最大公共前后缀长度、样本串的next数组(下一步回溯样本串的比较位置)
类库中String类的indexOf();方法采用的KMP算法,常规方法——依次暴力遍历,如果不匹配回溯到母字符串下一位置继续进行比较!
在这里存在一个问题,回溯到下一位置可能导致很多多余比较操作!例如下面示例:
母串:ABABABABACABCAB
样本串:ABABABC
在上述比较中,进行多次多余回溯操作(多次比较无意义)
既然很多次回溯操作无意义,那么现在找到哪些无意义的回溯,即找到合适正确回溯位置(next数组)!!
推导过程
母串:ABABABABACABCAB
样本串:ABABABC
// 这里位置不是按数组0位开始。
第一次比较在第7位发现与母串不同,那么我们肉眼观察下,下一次比较为
ABABABABACABCAB
ABABABC
这样最为合理(即母串的第7位与样本串的第5位进行比较)。
那么为什么选择该回溯位置??
那么我们简单看下ABABC这个样本串
样本串 ABABABC 假如与未知字符串比较,那么求出当未知字符串第i位匹配不同时,样本串与未知字符串第i位重新比较的位置,即为样本串的next数组。
怎么求出其对应的next数组?
样本串 ABABABC,如果第5个位置与未知字符串不同,那么前4位为 ABAB , (此处可以理解为样本串后移)后移几位合适?后移则是比较前缀和后缀是否相同,其最大公共前后缀的长度几位下一次比较的样本串的位置。
问题转化为求取样本串的当前位置之前的最大公共前后缀的长度(next数组),也是KMP算法的核心部分。
A B A B A B C 的next数组。
0 0 0 1 2 3 4
已知next数组后循环母表逻辑流程图如下:
indexOf()的示例代码如下:
class Solution {
/**
* 寻找最长公共前缀后缀的长度
* 示例:ABABCABAB
* 前缀集合(不包含示例本身):A, AB, ABA, ABAB, ABABC, ABABCA, ABABCAB, ABABCABA
* 后缀集合(不包含示例本身):B, AB, BAB, ABAB, CABAB, BCABAB, ABCABAB, BABCABAB
* 最长公共前缀后缀为,ABAB;返回4
* @param needle 传入字符串
* @return 最长公共前缀后缀的长度
*/
public static int publicPrefix(String needle