KMP 算法主要是通过消除主串指针的回溯来提高匹配效率的,那么它是怎样来消除回溯的呢?
从主串s中寻找子串t的位置,示例代码:
#define MaxSize 100
typedef struct
{
char data[MaxSize];
int length; //串长
} SqString;
//求子串t中j与k的关系(k = next[j],其中j为字符下标,k为j前面的字符串最长相等前后缀的长度)
void GetNext(SqString t, int next[])
{
int j = 0;
int k = -1;
next[0] = -1;
while (j < t.length - 1)
{
if (k == -1 || t.data[j] == t.data[k])
{
j++; k++;
next[j] = k;
}
else
{
k = next[k];
}
}
}
int KMPIndex(SqString s, SqString t)
{
int next[MaxSize], i = 0, j = 0;
GetNext(t, next); //求子串t中j与k的关系
while (i < s.length && j < t.length) //从前往后对主串和子串每个字符进行比较
{
if (j == -1 || s.data[i] == t.data[j])
{
i++; j++; //i,j后移
}
else
{
j = next[j]; //i不变,j回退至前缀后一个字符位置
}
}
if (j >= t.length)
return i - t.length; //匹配成功,返回主串中子串位置
else
return -1; //匹配失败,返回-1
}
int _tmain(int argc, _TCHAR* argv[])
{
SqString s;
cin >> s.data;
s.length = strlen(s.data);
SqString t;
cin >> t.data;
t.length = strlen(t.data);
int a = KMPIndex(s, t);
cout << a << endl;
system("pause");
return 0;
}
KMP算法的核心在与求next[]数组,即求子串t中的j与k的关系(k = next[j],其中j为字符下标,k为j前面的字符串最长相等前后缀的长度)。
我给大家个例子。
字符串 abcdab
前缀的集合:{a,ab,abc,abcd,abcda}
后缀的集合:{b,ab,dab,cdab,bcdab}
那么最长相等前后缀就是ab,长度k=2。