KMP浅显理解
KMP算法解释
1.好的博客
从头到尾彻底理解KMP算法,这是我在搜索各种博客之后,解释的最为详尽的一篇关于介绍KMP算法的一篇博客。自己的理解也算是建立在这篇博客上。很早很早之前就已经学过了,不过还是忘了好多。现在再拾起来按照自己的理解疏解一遍。
2.KMP缘何而起
目标问题,给你一个文本串S,文本串T求出S中与T相匹配的第一个位置。
我们有朴素的算法是:
int j=1;
int i=1;
int s0=strlen(S);
int tp=strlen(T);
while(i<=s0&&j<=t0)
{
if(S[i]==T[j])
{
i++;
j++;
}
else
{
i++;
j=1;
}
}
这是最为简单的暴力算法,同时我们也会发现,每一次匹配不成功的时候我们都会要去从头开始匹配。
a | b | c | d | e |
---|---|---|---|---|
a | b | b | d | e |
如上图所示当abc与abb失配的时候我们会将a再与b去匹配,但是实际上我们早已经知道了第二个字符是b。所以如此显而效率会较为低下.
3.KMP算法解释
Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。
简要思路:当我们匹配到S字符串中的第i个位置的时候,此时匹配到T字符串的第j个字符,此时有i-j+1位置到i位置与T字符串中的字符相匹配。
如果第j+1个字符相匹配,接着向下进行匹配即可。
如果第j+1个字符失配,我们就控制S中字符位置不发生改变,将T向后滑动一段位置。(next[j])
我们先来看KMP算法的代码
int j=0;
int s0=strlen(S);
int t0=strlrn(T);
while(i<s0&&j<t0)
{
if(j==0||S[i]==T[j])
{
i++;
j++;
}
else
{
j=next[j];
}
if(j>t0)
return i-t0;
else
return 0;
}
代码中next即为向右滑动的值。那么如何去理解这个next值则成了关键,自己也被折磨了好久好久。
int j=0;
int i=1;
next[1]=0;
int t0=strlen(T);
while(i<t0)
{
if(j==0||T[j]==T[j])
{
i++;
j++;
next[i]=j;
}
else
{
j=next[j];
}
}
理解如下
A | B | C | D | A | B | C |
---|---|---|---|---|---|---|
A | B | C | D | A | B | D |
A | B | C | D | A | B | D |
---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 1 | 1 | 2 |
在这里j所表示的含义代表着第j个字符位置前面与T字符串从头开始最大匹配长度。拿上面表格举例来说,在最后一个位置我们发生了失配问题,D之前与字符串T从头匹配最大长度为2,截至到C为止。所以我们就将字符串的位置滑到了C处。 next的值所表示的东西就是j处字符前面的字符与T字符串从头开始匹配的最大长度!!!
但其实截至到现在这个算法还不算完美,因为我们还会有一种极特殊的情况。
A | A | A | A | A | B |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 |
比如上面表格所列处的这种结构当B失配的时候我们右移到了左边的A的位置,A失配后我们右移到了第四个A的位置,但显然我们之前已经知道了肯定会失配的结果。
a | b | a | d | e |
---|---|---|---|---|
a | b | a | b | e |
0 | 1 | 1 | 2 | 1 |
b失配移到了第二个位置但这个时候还是b,所以所得结果依然会是失配,明知故作?
实际上是我们求next的过程中有点小疏漏,这个时候应该要能够满足如果j==T[next[j]]那么j=next[next[j]],因为如果T[j]=T[next[j]]则肯定失配,则应该尽量避免这种状况。
int j=0;
int i=1;
int t0=strlen(T);
while(i<=t0)
{
if(j==0||T[j]==T[i})
{
i++;
j++;
if(T[i]!=T[j])
next[i]=j;
else
{
next[i]=next[j];
}
}
else
{
j=next[j];
}
}
自己目前也理解的不是特别充分,也只能将自己想出来的,大概写出来成这个样子了,实在理解不了的话可以采取强制记忆措施,只不过实在不是太好的样子。
up!up!
上一篇: 第05课:服务注册与发现
下一篇: 豆瓣电影top250下的评论爬取