#include <iostream>
#include <string>
#include <vector>
using namespace std;
void get_next1(string T, int *next){
int i, j;
i = 1;
j = 0;
//next下标从1开始计数
next[1] = 0;
//i的范围 [1, j-1]
while(i < T.size())
{
//T[i] 表示T的前缀字符, T[j] 表示T的后缀字符
//如果j == 0时, T没有字符,都往后推一位,此时有一个字符
//如果前后缀字符相等,则往后推一位,继续判断后一位是否相等
if(0 == j || T[i] == T[j])
{
++i;
++j;
//如果有一位字符相等,此时,j=1, i=2, next[2]=1;
//如果有两位字符相等,此时,j=2, i=3, next[3]=2;
next[i] = j;
}
//如果字符在此失配,回溯j,从即上一次匹配到的相同处处开始匹配
//例如:S: ababcderf T: ababe
//下标j 12345
//此时 j=5时失配,next[5]=3,j被置为3,从第二个“ab”处的a开始匹配
else
j = next[j];
}
}
//此处为KMP算法的改进
//例如:S: aaaabcdef T: aaaaax
//下标j 123456
void get_next2(string T, int *next){
int i, j;
i = 1;
j = 0;
next[1] = 0;
while(i < T.size())
{
if(0 == j || T[i] == T[j])
{
++i;
++j;
//如果在T串相同字符中出现了与S串的失配
if(T[i] != T[j])
//直接将当前位置的字符赋值给next的i位置的值,直接从此匹配
next[i] = j;
else
//如果没有失配,则将j位置的next值赋给i位置next的值
next[i] = next[j];
}
else
j = next[j];
}
}
size_t kmp(string S, string T, size_t pos){
size_t i = pos;
int j = 1;
int next[1000];
//get_next1(T, next);
get_next2(T, next);
next[0] = T.size();
while(i <= S.size() && j <= T.size())
{
if(0 == j || S[i] == T[j-1])
{
++i;
++j;
}
else
j = next[j];
}
if(j > T.size())
return i - T.size();
else
return 0;
}
int main(int argc, char *argv[])
{
//string s = "ababcababxwd", t = "ababx";
string s = "aaaabcdeaaaaaxw", t = "aaaaax";
size_t sz = kmp(s, t, 0);
cout<<sz<<endl;
return 0;
}
数据结构c++实现——串的KMP算法
最新推荐文章于 2024-06-23 23:51:02 发布