KMP算法
设有两个串s和t,在串s中找到一个与t相等的子串。通常把s称为目标串,把t称为模式串。在目标串s中找到了一个模式串t则模式串匹配成功,没有找到则匹配不成功。
设n为串s的长度,m为串t的长度。
为什么要使用KMP算法?
模式匹配串是一个比较复杂的串操作,用暴力的方法来做的话,复杂度为O(m*n),但如果使用KMP算法,复杂度为O(m+n),大大提高了算法效率。
从模式串t中提取出加速匹配的有用信息,使每一次匹配不需要重头开始,而是回溯。
为了取得模式串 t中每个位置的信息,我们采用next数组表示,即next[j]=MAX{k}。(j为位置信息,k<j,模式串t中开头的k个字符依次与t[j]前面k个字符相同,取k的最大值)
next表
void GetNext(SqString t,int next[])//由模式串t求出next数组
{
int j,k; //j扫描t,k记录t【j】之前与t开头相同的字符个数
j=0;k=-1;
next[0]=-1; //设置next[0]的值
while(j<t.length-1)
{
if(k==-1||t.data[j]==t.data[k])//k为-1或者比较的字符相同时
{
j++;k++;//j,k依次移动到下一个字符
next[j]=k;//设置next[j]=k
}
else
k=next[k];//k回退
}
例如模式串"abcabaa"
j | t[j] | next[j] |
---|---|---|
0 | a | -1 |
1 | b | 0 |
2 | c | 0 |
3 | a | 0 |
4 | b | 1 |
5 | a | 2 |
6 | a | 1 |
KMP算法
以此为例
next表为
j | t[j] | next[j] |
---|---|---|
0 | a | -1 |
1 | a | 0 |
2 | a | 1 |
3 | b | 2 |
第一次匹配从i=0,j=0,开始,失配处为i=3,j=3;
next[3]=2,则下一步为i=3,j=2;
匹配完成
对应的KMP算法如下
int KMPIndex(SqString s,SqString t)
{
int next[MaxSize],i=0,j=0;
GetNext(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1||s.data[i]==t.data[j])
i++;j++;
else
j=next[j];
}
if(j>=t.length) //匹配成功
return(i-t.length) //返回字符串位置
else //匹配不成功
return -1; //返回-1
}
对于KMP算法的话,如果还不怎么懂,多看一些例子比较好,看得多了就有那种感觉了。