KMP算法
KMP算法用来解决字符串匹配的问题,传统的暴力匹配会导致每一次匹配失效,主串自动回到的当前主串的头部位置的下一个位置继续匹配,这样会带来性能损失。可以看以下示例:
所以KMP就对此模式串做了优化,最关键的优化就是求next
数组。
比如说ABABC
的next
数组就是00120
。
完整KMP匹配算法如下所示:
#include<iostream>
#include<string>
#include<vector>
#include<functional>
using namespace std;
vector<int> getNext(string& s){ //核心点
vector<int> next(s.size(), 0);
int prefixLen = 0, index = 1;
while(index<s.size()){
if(s[prefixLen]==s[index]){
++prefixLen;
next[index] = prefixLen;
++index;
}
else{
if(prefixLen==0){
next[index] = 0;
++index;
}
else{
prefixLen = next[prefixLen - 1];
}
}
}
return next;
}
vector<int> kmpSearch(string& matchStr,string& patternStr,vector<int>& next){
vector<int> ans;
if(patternStr.size()>matchStr.size()){
return ans;
}
for (int i = 0, j = 0; i < matchStr.size();){ //i和j的匹配失效是笔试面试常考点
if(matchStr[i]==patternStr[j]){
++i;
++j;
}
else{
if(j==0){
++i;
}
else{
j = next[j - 1];
}
}
if(j==patternStr.size()){
ans.push_back(i - j);
j = 0;
}
}
return ans;
}
int main(){
string patternStr = "ABA";
vector<int> next = getNext(patternStr);
function<void(vector<int>)> printVec = [&](vector<int> vec) -> void {
for(auto t:vec){
cout << t << " ";
}
cout << endl;
};
printVec(next);
string matchStr = "AABABADDABAC";
vector<int> ans = kmpSearch(matchStr, patternStr, next);
printVec(ans);
return 0;
}
参考资料
https://zhuanlan.zhihu.com/p/145536254