KMP算法
#include <iostream>
#include <string>
#include <vector>
using namespace::std;
vector<int> GetNext(string str)
{
vector<int> next(str.size());
//next數組含義:如果str[i]不匹配,在str[i]之前:next[i]個後綴與 next[i]個前綴是相同的,(前綴和後綴是不能等於字符串本身的)
//所以應該跳轉到(str[next[i]])處,這樣可以將next[i]個前綴與後綴完全重合,繼續比較
//next[i]存的是 str[i] 的第一長的相同前綴後綴的長度,
//next[next[i]]存的是 str[i] 的第二長的相同前綴後綴的長度...依次類推
if (str.empty())
return next;
int j = 0;
int k = -1;
next[j] = k;
//str[j]爲後綴最後一位,str[k]爲前綴最後一位
//如果str[0]不匹配,str[0]前:有0個後綴與0個前綴相同,所以應該跳轉到(0)處
//但是str[0]==str[0],所以next[0]存放-1,當調整到str[-1]時,意味着需要整體右移一位
while (j<str.size()-1)
{
if (k == -1||str[j]==str[k])
{
++k;//最長前綴後綴加1:k+1
++j;//存到next數組的j+1處
next[j] = k;
}
else
{
k = next[k];
}
}
//去除無效跳轉,如果當前字符不匹配,且跳轉後的字符和當前字符一樣,則調整後肯定還是不匹配,需要繼續跳轉
for (auto i = 0; i < next.size();++i)
{
int k = next[i];
while (k != -1 && str[i] == str[k])
{
k = next[k];
}
next[i] = k;
}
return next;
}
int KMPSearch(string str, string pstr)
{
vector<int> next = GetNext(pstr);
int i = 0, j = 0;
int slen = str.size();
int plen = pstr.size();
while (i < slen&&j < plen)
{
if (j == -1 || str[i] == pstr[j])
{
++i;
++j;
}
else
{
j = next[j];
}
}
if (j == pstr.size())
{
return i - j;
}
else
{
return -1;
}
}
int main()
{
string pstr = "abab";
string str = "asdfafasfaababfasgdga";
cout<<KMPSearch(str, pstr)<<endl;
return 0;
}