以前刚学的时候迷迷糊糊的,一看就懵圈,前几天捡起来的时候 发现还不会
于是研究了两天,自尊心严重受挫,今天的时候 突然一道灵光迸发,居然
感觉好像懂了,于是又琢磨起来 终于 我懂了 呵呵!
0 1 2 3 4 5 6 7 8 9
主串 : a b c d e a b c d f
i
0 1 2 3 4 5 6 7 8 9
模式串: c d f
j
i=4时 e!=f匹配失败 传统字符匹配是让i=3,j=0继续匹配,i++,j=0.
此种匹配方式虽然简单易懂,但是多了许多次无用的回溯比较(如 i=3,j=0)
因此kmp算法横空出世,讲真,我真心佩服发明这个算法的人,太屌。。。
看毛片算法采用滑动模式串的方式 ,有效的避免了无用回溯
-------------------------------------------------------------------
我对 kmp算法的理解
两个字符串
0 1 2 3 4 5 6 7
a b c a b a a b a e f(用i指向字符)
a b a e(用j指向字符)
i=3,4,5等于j=0,1,2 而i=6不等于j=3
这时传统思想是将j=0,i=4依次比较。而kmp算法是利用移动模式串的方式来解决字符匹配问题
因为 i=3,4,5 等于 j=0,1,2
所以i=5 等于 j=2
而 j=0 等于 j=2 则不需要匹配j=0与i=4的无效匹配,直接将模式串向右移动两位即可
//问题一:为什么j=0与i=4是无效匹配?
// 1.模式串已知 j=0不等于j=1
// 2.i=4等于j=1 而 j=0不等于j=1 所以 j=0指定不等于i=4
// 所以不用比较
//问题二:为什么向右移动两位?
// 距离 L=length(模式串)-next[j](减的始终是数组中最大的元素);
a b a e
next[j]= 0 1 1 2
看毛片算法的实现
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
int len(char *t)
{
int i=0,j=0;
char *m;
for(m=t;t[i]!=‘\0‘;i++)//m,t代表的都是首地址
{
j++;
}
return j;
}
void makenext(char *p,int next[])
{
int k=0,q;
int m=len(p);
next[0]=0;
for(k=0,q=1;q<m;q++)
{
while(k>0&&p[k]!=p[q])
k=next[k-1];
if(p[k]==p[q])
{
k++;
}
else
{
next[q]=k;
}
}
}
int kmp(char * t,char * p,int next[])
{
int i=0,q=0,k;
int pos;
int lent=len(t);
int lenp=len(p);
//t[0]=lent;//类型不一致可能用到强制转换;
//p[0]=lenp;
makenext(p,next);
for(i=0,q=0;i<lent;i++)
{
while(q>0&&t[i]!=p[q])
q=next[q-1];
if(t[i]==p[q])
{
q++;
}
if(q==lenp)
{
printf("在位置n匹配完成:%d",(i-lenp+1));
}
}
}
int main()
{
int i=0;
int lent,lenp,pos;
int next[]={0};
char *text="abcababeca";
char *patten="ababe";
printf("%s\n " ,text);
printf("%s\n " ,patten);
kmp(text,patten,next);
return 0;
}
参考大神的博客------http://www.cnblogs.com/c-cloud/p/3224788.html