字符串匹配——KMP算法

来源:互联网 发布:狼牙军品专卖店一淘宝 编辑:程序博客网 时间:2024/05/21 03:16

先附上一份我觉得解释很详细的文章:
匹配基本流程和前后缀
next数组求法与解释
KMP算法之所以是线性复杂度,就在于不需要重复匹配对比,通过next调到最近的有必要匹配检查的位置。
换句话说,就是对于被匹配串,每当在当前节点发生不匹配,为了不浪费之前匹配成果和避免遗漏,跳到拥有相同前缀的位置继续比较。
不懂?不要紧,看着下面代码注释,相信会有新的发现。
奉上一道水题:
剪花布条
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
Input
输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
Output
输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
Sample Input
abcde a3
aaaaaa aa
#
Sample Output
0
3

#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define maxsize 1010//str1是源字符串,str2是需要寻找的字符串char str1[maxsize],str2[maxsize];//记录跳表int Next[maxsize];//获得跳表void getnext(){    int i=0,j=-1;//i是当前找到的位置,j是从开头找    //    Next[0]=-1;    int m=strlen(str2);    //为每一个位置上的字母寻找跳表值    while(i<m)    {        //如果是-1,代表刚开始或者前一位置匹配失败,且不存在拥有相同前缀的组成        //后者比较好理解,就是前缀和后缀当前位置拥有相同字符,        //每个位置next的值是当前位置前缀和后缀拥有的最大公共长度        //当新读入的一位和前缀读到的位置的字母相同,自然最大长度会加一        if(j==-1||str2[i]==str2[j])        {            i++;            j++;            Next[i]=j;        }        //新读入的一位和前缀读到的位置的字母不相同,自然最大长度从头开始重新找        //因为前缀一定从第一位开始向后计算        //所以一旦不一样,就可以跳到第next【j】个位置        //(如果j不为0,说明有一段是匹配的,也就是从开头到第j个之前还是一样的)        //此时,如果是-1,说明之前从没有到达这个长度,此时只能从头开始重新计算,接上一步j==-1        //如果不是-1而是确切的值,说明之前有过有相同前缀的子串,则在此基础上继续找,接上一步str2[i]==str2[j]        else        {            j=Next[j];        }    }}//匹配过程int kmp(){    int n=strlen(str1);    int m=strlen(str2);    int i=0,j=0,cnt=0;    while(i<n)    {        //如果重头来或者相同        if(j==-1||str1[i]==str2[j])        {            i++;            j++;        }        else        {            j=Next[j];        }        //完全匹配        if(j==m)        {            j=0;            str1[i-1]='0';            cnt++;        }    }    return cnt;}int main(){    while(scanf("%s",str1))    {        memset(Next,-1,sizeof(Next));        if(str1[0]=='#') break;        else        {            scanf("%s",str2);            getnext();            printf("%d\n",kmp());        }    }    return 0;}

本人萌新小白一枚,若有错误,还望不吝赐教。

原创粉丝点击