KMP算法理解
设模式串为pattern[0,1,2…p-1]
核心思想
- 找到模式子串pattern[0,1,2…k-1]的真后缀同时也是pattern[0,1,2…p-1]的最大前缀的长度(pattern的总长度是p,0<=k<=p),存入pi数组。
- 利用pi数组来避免模式串和主串的不必要的比较,提高效率
KMP算法C++代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//得到模式串的pi数组
void get_pi(string pattern, int plen, int *pi){
if (pattern.size() == 0) return;
int k = -1;
pi[0] = -1;
for (int i = 1; i < plen; i++){
while (k > -1 && pattern[i] != pattern[k + 1])
k = pi[k];
if (pattern[i] == pattern[k + 1])
k = k + 1;
pi[i] = k;
}
return;
}
//找到所有的模式串在主串中的位置,并存入vector中返回
vector<int> search_substr(string str, string pattern){
vector<int> subindex;
int plen = pattern.length(), strlen = str.length(), q = -1;
int *pi = new int[plen];
get_pi(pattern, plen, pi);
for (int i = 0; i < strlen; i++){
while (q > -1 && str[i] != pattern[q + 1])
q = pi[q];
if (str[i] == pattern[q + 1])
q = q + 1;
if (q == plen - 1)
{
subindex.push_back(i-plen+1);
q = pi[q];
}
}
delete[] pi;
return subindex;
}
//主函数
int main(){
string str = "ababcabcacbabcac";
string pattern = "abcac";
vector<int> subindex = search_substr(str, pattern);
for (auto iter : subindex){
cout << iter<< endl;
}
getchar();
return 0;
}