KMP算法是判断两个字符串str1中是否包含与str2相同的子串。
next数组概念
KMP算法最关键的就是next数组。next数组就是针对str2串中每个字符前的子串中存在的前缀与后缀匹配的最长长度。假设str2为“abababca”。
j=0,字符str2[j]=a,a前没有字符串,默认为next[0]=-1;
j=1,字符str2[j]=b,b前子串为“a”,前后缀不存在,默认为next[1]=0;
j=2,字符str2[j]=a,a前子串为“ab”,前后缀不存在相等,则next[2]=0;
j=3,字符str2[j]=b,b前子串为“aba”,前后缀最大相等为a,则next[3]=1;
以此类推next[9]=[-1,0,0,1,2,3,4,0]
KMP匹配过程
next求法
通俗易懂的话来说就是你要求解当前位的next值,则看前一位与前一位next所在位字符是否相等,相等则当前位的next等于前一位next+1,如果不等就找前一位next的next与前一位比较,如果相等,当前位的next等于那个与前一位字符相等的字符所在位置+1,如果还是不相等,则以此类推,直到出现比较位为next[]=-1,那当前位的next就等于-1。
#include<iostream>
#include<thread>
#include<string>
#include<vector>
using std::cout;
using std::endl;
void getNext(int *next,const std::string &str) {
int i = 0;
next[0] = -1;
int k = -1;
while (i < (str.length() )) {
if (k == -1 || str[i] == str[k]) {
++i;
++k;
next[i] = k;
}
else {
k = next[k];
}
}
}
bool subString(const std::string &str1, const std::string &str2, std::vector<int> &position) {
int *next = new int[str2.length()+1];
getNext(next, str2);
int i = 0; // str1
int j = 0;// str2
while (i<str1.length()){
if (j == -1 || str1[i] == str2[j]) {
++i;
++j;
if (j >= str2.length()) {
position.push_back(i - str2.length());
j = next[j];
}
}
else{
j = next[j];
}
}
delete[] next;
if (position.empty()) {
return false;
}
else{
return true;
}
}
int main() {
std::string str1 = "abababbbab";
std::string str2 = "aba";
std::vector<int> position;
subString(str1, str2, position);
for (auto it = position.begin(); it != position.end(); ++it) {
cout << (*it) << endl;
}
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return 0;
}
其中很多参考杨守乐文章:http://mp.weixin.qq.com/s/2o2KLILAaFDf-aMDoLnbsA