您的位置:首页 > 其它

KMP,扩展KMP模板

2017-09-04 09:36 405 查看
KMP算法#include<iostream>
#include<string>
using namespace std;

/* P为模式串,下标从0开始 */
void GetNext(string P, int next[])
{
int p_len = P.size();
int i = 0; //P的下标
int j = -1;
next[0] = -1;

while (i < p_len)
{
if (j == -1 || P[i] == P[j])
{
i++;
j++;
next[i] = j;
}
else
j = next[j];
}
}

/* 在S中找到P第一次出现的位置 */
int KMP(string S, string P, int next[])
{
GetNext(P, next);

int i = 0; //S的下标
int j = 0; //P的下标
int s_len = S.size();
int p_len = P.size();

while (i < s_len && j < p_len)
{
if (j == -1 || S[i] == P[j]) //P的第一个字符不匹配或S[i] == P[j]
{
i++;
j++;
}
else
j = next[j]; //当前字符匹配失败,进行跳转
}

if (j == p_len) //匹配成功
return i - j;

return -1;
}
优化版

/* P为模式串,下标从0开始 */
void GetNextval(string P, int nextval[])
{
int p_len = P.size();
int i = 0; //P的下标
int j = -1;
nextval[0] = -1;

while (i < p_len)
{
if (j == -1 || P[i] == P[j])
{
i++;
j++;
if (P[i] != P[j])
nextval[i] = j;
else
nextval[i] = nextval[j]; //既然相同就继续往前找前缀
}
else
j = nextval[j];
}
}

扩展KMP算法

#include<iostream>
#include<string>
using namespace std;

/* 求解T中next[],注释参考GetExtend() */
void GetNext(string T, int next[])
{
int t_len = T.size();
next[0] = t_len;
int a;
int p;

for (int i = 1, j = -1; i < t_len; i++, j--)
{
if (j < 0 || i + next[i - a] >= p)
{
if (j < 0)
p = i, j = 0;

while (p < t_len&&T[p] == T[j])
p++, j++;

next[i] = j;
a = i;
}
else
next[i] = next[i - a];
}
}

/* 求解extend[] */
void GetExtend(string S, string T, int extend[], int next[])
{
GetNext(T, next); //得到next
int a;
int p; //记录匹配成功的字符的最远位置p,及起始位置a
int s_len = S.size();
int t_len = T.size();

for (int i = 0, j = -1; i < s_len; i++, j--) //j即等于p与i的距离,其作用是判断i是否大于p(如果j<0,则i大于p)
{
if (j < 0 || i + next[i - a] >= p) //i大于p(其实j最小只可以到-1,j<0的写法方便读者理解程序),
{ //或者可以继续比较(之所以使用大于等于而不用等于也是为了方便读者理解程序)
if (j < 0)
p = i, j = 0; //如果i大于p

while (p < s_len&&j < t_len&&S[p] == T[j])
p++, j++;

extend[i] = j;
a = i;
}
else
extend[i] = next[i - a];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: