KMP-字符串匹配

来源:互联网 发布:自己的域名 编辑:程序博客网 时间:2024/06/05 21:13

模式匹配算法,不退化地在线性时间内完成模式匹配

目的:在目标串中找到模式串
作用:预处理出模式串的匹配信息,节省不必要的匹配时间

比如:有两个串 aacdeeaacc aacc
先匹配第一位,发现匹配,再匹配第二位,第三位,直到第四位不符合,此时,将搜索词aacc后移一位,重复上述操作,可以看出,后面的a【acdee】aacc acdee是没有必要比较的,可以直接匹配后面的aacc,所以,如何做到这一点呢?

实际上,我们的目的就是想让串越过一些没必要的部分,直接移到有匹配成功的可能的位置,那目标变为了怎样计算需要越过去的位数,这就用到了next[].

通俗一点,next[]记录的就是 前i位中前后缀的共有元素的最大值,我们称为记录“部分匹配”(字符串匹配过程中失配情况下可以向前多跳几个字符)

补充:

以aacdeeaacc为例,好像有点长,用abcde吧前缀:a,ab,abc,abcd (除结尾字符)后缀:bcde,cde,de,e  (除开头字符)

“部分匹配”的实质是,字符串头,尾可能会有重复。比如,”abcdab”之中有两个”ab”,那么它的”部分匹配值”就是2(”ab”的长度)。搜索词移动的时候,第一个”ab”向后移动4位,就可以移动到第二个”ab”的位置。
即: 使串 移到部分匹配值所对应的后缀的位置

**移动位数=已匹配的字符数-对应的部分匹配值=中间越过的位数**

但要注意,遇到可以匹配上一部分的才可以用next后移到与它相同的后缀处,保证后面可以有匹配上的可能

//求模式串(所求串)在目标串(原串)中出现的次数 , 可重叠 #include<algorithm>#include<cstring>#include<cstdio>#define N 1010using namespace std;char s[N],p[N];//所求串 , 原串 int nxt[N];//失配情况下可以向前多跳几个字符 //int len;void get_nxt(char * p)//帮助越过没必要匹配的位置 {    int i=0,j=-1;     nxt[i]=j;//nxt[0]=-1;    while(p[i])//p不为空时,就是要记录完每个位置的nxt     {//i:1~n        if (j==-1||p[j]==p[i]) nxt[++i]=++j;        else j=nxt[j];     }}/*void get_nxt(){    int j=-1,i=0;    nxt[0]=-1;    while(i<len)    {        if(j==-1||ss[i] == ss[j])        {            i++;            j++;            nxt[i]=j;        }        else        {            j=next[j];        }    }}*/int kmp(char *s,char *p){    get_nxt(p);//处理nxt     int i=0,j=0,ret=0;    for (;s[i];++i) //若 int i=1,则i++     {        while (j!=-1&&s[i]!=p[j]) j=nxt[j];        j++;        if (!p[j])        {            ret++;             j=nxt[j];            //operations        }    }    return ret;}int main(){    scanf("%s%s",s,p);//  len=strlen(p);    printf("%d\n",kmp(s,p));    return 0;}

@有错误,请指出哟(^U^)@

原创粉丝点击