序
对于字符串章节的模式匹配,一直都很排斥去深入学习。不过逃避总归解决不了问题,还是硬着头皮去看吧~
KMP代码
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
/*********************************************************************
普通模式匹配算法
*********************************************************************/
/*返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。
* T非空, 0<=pos<S.length()
*/
int index1(string S, string T, int pos)
{
/*i用于主串S中当前位置下标,若pos不为0,则从pos位置开始匹配*/
int i = pos;
/*j用于子串T中当前位置的下标值*/
int j = 0;
/*若i小于S长度且j小于*/
int sLen = S.length(), tLen = T.length();
while (i < sLen && j < tLen)
{
if (S[i] == T[j])
{
++i;
++j;
}
else {
/*i回退到上次匹配首位的下一位*/
i = i - j + 1;
j = 0;
}//else
}//while
if (j >= tLen)
return i - tLen;
else
return -1;
}
/*********************************************************************
KMP算法
*********************************************************************/
/*通过计算返回子串T的next数组*/
void getNext(string T, vector<int> &next)
{
int i = 0, j = 0;
next[i] = 0;
int tLen = T.length();
while (i < tLen)
{
if (j == 0 || T[i] == T[j])
{
++i;
++j;
next[i] = j;
}else{
j = next[j];
}
}
}
/*返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。
* T非空, 0<=pos<S.length()
*/
int KMP(string S, string T, int pos)
{
/*i用于主串S中当前位置下标,若pos不为0,则从pos位置开始匹配*/
int i = pos;
/*j用于子串T中当前位置的下标值*/
int j = 0;
/*若i小于S长度且j小于*/
int sLen = S.length(), tLen = T.length();
vector<int> next(tLen + 1);
getNext(T, next);
while (i < sLen && j < tLen)
{
if (j == 0 || S[i] == T[j])
{
++i;
++j;
}
else {
j = next[j];
}//else
}//while
if (j >= tLen)
return i - tLen;
else
return -1;
}
/*********************************************************************
改进的KMP算法 -- 改进求next数组,以nextVal代替
*********************************************************************/
void getNextVal(string T, vector<int> &nextVal)
{
int i = 0, j = 0;
nextVal[i] = 0;
int tLen = T.length();
while (i < tLen)
{
if (j == 0 || T[i] == T[j])
{
++i;
++j;
if (T[i] != T[j])
nextVal[i] = j;
else
nextVal[i] = nextVal[j];
}
else {
j = nextVal[j];
}
}
}
int KMP2(string S, string T, int pos)
{
/*i用于主串S中当前位置下标,若pos不为0,则从pos位置开始匹配*/
int i = pos;
/*j用于子串T中当前位置的下标值*/
int j = 0;
/*若i小于S长度且j小于*/
int sLen = S.length(), tLen = T.length();
vector<int> nextVal(tLen + 1);
getNextVal(T, nextVal);
while (i < sLen && j < tLen)
{
if (j == 0 || S[i] == T[j])
{
++i;
++j;
}
else {
j = nextVal[j];
}//else
}//while
if (j >= tLen)
return i - tLen;
else
return -1;
}
int main()
{
string S = "goodgoogle", T = "google";
//cout << index1(S, T, 0) << endl;
cout << KMP(S, T, 0) << endl;
cout << KMP2(S, T, 0) << endl;
system("pause");
return 0;
}