KMP算法

void GetNextval(string partStr, vector& nextval)

{

int p_len = partStr.size();

//由 next[i] = j 得,也就是对于位置 i 来说,

//区段[0, i - 1] 的最长相同真前后缀分别是[0, j - 1] 和[i - j, i - 1],即这两区段内容相同。

int i = 0;  // P 的下标

int j = -1;

nextval[0] = -1;

while (i < p_len)

{

//  j == -1 存在的意义是何?

//  第一,程序刚运行时,j 是被初始为 -1,直接进行 P[i] == P[j] 判断无疑会边界溢出;

// 第二,else 语句中 j = next[j],j 是不断后退的,若 j 在后退中被赋值为 -1(也就是 j = next[0]),在 P[i] == P[j] 判断也会边界溢出。

// 综上两点,其意义就是为了特殊边界判断。

if (j == -1 || partStr[i] == partStr[j])

{

i++;

j++;

nextval[i] = j;

//为了防止出现ABCDAB 若在 i = 5 时匹配失败,此时应该把 i = 1 处的字符拿过来继续比较,

//但是这两个位置的字符是一样的,都是 B,既然一样,拿过来比较不就是无用功了么?

//所以将nextval[i] = j;优化,如果相同就继续往前找前缀

if (partStr[i] != partStr[j])

nextval[i] = j;

else

nextval[i] = nextval[j];  // 既然相同就继续往前找真前缀

}

else

j = nextval[j];

}

}

int  KMP(string mianStr, string partStr) {

int partLen = partStr.length();

vector nextList(partLen+1,0);

GetNextval(partStr, nextList);

int i = 0;

int j = 0;

while (i < mianStr.length()&& j < partLen)

{

if (j==-1|| mianStr[i] == partStr[j])

{

i++;

j++;

}

else

{

j = nextList[j];

}

}

if (j == partLen)

{

return i - j;

}

return -1;

}

你可能感兴趣的:(KMP算法)