http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html
字符串匹配的KMP算法
转载一下,UP主已经写的很详细了,超赞!!
/////////////////////////////////////割//////////////////////////////////////////////////////
对KMP算法,网上可真是铺天盖地的介绍,说什么的都有,未免会让人看的摸不到头脑,为了把代码敲出来,看了几个up主的视频,哔哩哔哩上面有,这里我就简介一下,尽量简单清楚!
首先就是next[]数组,我要首先告诉你的是
shuzu | a | b | c | d | a | b | d |
next | 0 | 0 | 0 | 0 | 1 | 2 | 0 |
这个next是绝对对的,但为什么我们见到的next都是这样的呢?
next | -1 | 0 | 0 | 0 | 0 | 1 | 2 |
这个是使用在程序里面的,把真正的next向后移动一位即可。
好,我们接着说KMP怎么用程序实现,这里楼主试着使用一种很通俗的比喻来代替,当然,这个可以选择不看,因为我发现如果有人问KMP原理是什么,我发现很难表述,倒不如打个比方,心里清楚,能够呼之欲出就OK,懂得程序怎么写。
/*
初始化next[]做为存放,cur作为变量初始值cur=0,cur[0]=0;
shuzu[]存放用户输入字符串,j作为变量初始值j=1;
eg1:abcdabca
我们观察发现,如果shuzu[j] !=shuzu[cur],即a!=d
很大程度直接next[j]就等于0了,但是发现,咦,shuzu[j]==shuzu[0]啊,那他填1,
我们总结:如果计算机走啊走啊,一直都相等,突然发现第shuzu[j]!=shuzu[cur],直接写cur=0;
然后判断shuzu[0]==shuzu[j],不就行了?找这个不匹配元素是否与第一个元素相等,好像很完美啊!
但是很不幸还有一种特殊情况
eg2:ABCDABCDEABCDABCDAF
老大顾不上你个小事情,那好吧,一级一级向上反映嘛
可以找老大的“代理人”谈,
代理人怎么找?
ABCDABCDE 与 ABCDABCDA在第九处不匹配,此时cur=8,j=13;
使cur=next[cur-1];
解释一下:
next[cur-1]=next[7]=4;
这个next[7]存放的4是什么意思呢,
说明前八个元素可以凑成一对,最长长度4,
既然成对,那也就是说shuzu[4]就是我shuzu[0]的代理人
我可以比较shuzu[4]==shuzu[j]
这样cur=4;而不是cur=0;
eg3:abcdabd
abc与abd
第三个元素不匹配,行,这次吸取经验,谁让可能会出错呢,那就一级一级上访
cur=next[cur-1]=next[1];
很明显next[1]=0;所以cur=0;
看来最终还是交给老大处理了嘛。。。。
*/
我们通俗的码一下代码:求真实的next[]
void get_next(char *shuzu,int *next)//传进要求next值的数组
{
int cur=0,j=1;//初始化两个变量作为游标
next[cur]=0;//直接把第一个元素赋0
while(j<len)//len=strlen(shuzu)
{
if(shuzu[cur]==shuzu[j])
{
cur++;
next[j++]=cur;//如果匹配接着往下面走,j先使用再加一
}else
{
if(cur>0)
cur=next[cur-1];
else
next[j++]=0;//此时cur已经等于零
}
}
}
这时把得到的next[]转换为程序需要的,只需要全部向后移动一位,把next[0]=-1即可
void move(char *next)
{
for(int i=n-1;i>0;i--)//n为next长度
{
next[i]=next[i-1];
}
next[0]=-1;
}
准备工作做好,可以写KMP了
void search_KMP(char *shuzu,char *T)//输入搜索和被搜索串,返回找到时候的位置
{
int cur,j;
while(j<strlen(shuzu))
{
if(cur==-1||shuzu[j]==T[cur])//如果T的首个元素也不匹配,统一向下移动一个元素
{
if(cur=strlen(T)-1)//找到匹配
{
cout<<"POS:"<<j-cur;
cur=next[cur];//继续寻找
}
j++;
cur++;
}else
{
cur=next[cur];
}
}
}
先写到这里吧,KMP写法比较多,还有一种常见的,直接next[0]=-1;不需要移动,再更。。。。18/9/5