两种KMP题+KMP模版整理

来源:互联网 发布:美工字体怎么写好看 编辑:程序博客网 时间:2024/06/05 04:31
最近稍微看了下KMP,不是很懂他们大神的A题姿势,但是模版总该还是要去学的。

其中next数组的求法有两处区别。

第一种:求主串中模式串的个数。HDU2087 剪花布条和HDU4847 Wow! Such Doge!。这两道都比较水可以暴力string::find函数过,

第一个代码:

#include<iostream>#include<algorithm>#include<cstdlib>#include<sstream>#include<cstring>#include<cstdio>#include<string>#include<deque>#include<cmath>#include<queue>#include<set>#include<map>using namespace std;typedef long long LL;int nextval[101010];void getnext(char s[],int next[]){    int j=0,k=next[0]=-1;    int len=strlen(s);    while (j<len-1)  //    {        if(k==-1||s[k]==s[j])            next[++j]=++k;          else            k=next[k];    }}int sea(char s[],char t[]){    int cnt=0;    int i=0,j=0;    int la=strlen(s),lb=strlen(t);    while (i<la&&j<lb)    {        if(j==-1||s[i]==t[j])        {            i++;            j++;        }        else            j=nextval[j];        if(j==lb)        {            cnt++;            j=0;                    }        }    return cnt;}int main(void){    char a[1010]={0},b[1010]={0};    while (cin>>a)    {        if(strcmp(a,"#")==0)        {            break;        }        cin>>b;        memset(nextval,0,sizeof(nextval));                getnext(b,nextval);        cout<<sea(a,b)<<endl;        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));    }    return 0;}

后一题代码:

#include<iostream>#include<algorithm>#include<cstdlib>#include<sstream>#include<cstring>#include<cstdio>#include<string>#include<deque>#include<cmath>#include<queue>#include<set>#include<map>using namespace std;typedef long long LL;int nextval[101010];void getnext(char s[],int nextval[]){    int j=0,k=-1;    nextval[0]=-1;    int lenp=strlen(s);    while(j<lenp-1)    //    {        if(k==-1||s[j]==s[k])            nextval[++j]=++k;//                   else            k=nextval[k];    }}int sea(char s[],char t[]){    int cnt=0;    int i=0,j=0;    int la=strlen(s),lb=strlen(t);    while (i<la&&j<lb)    {        if(j==-1||s[i]==t[j])        {            i++;            j++;        }        else            j=nextval[j];        if(j==lb)        {            cnt++;            j=0;                    }        }    return cnt;}void change(char a[]){    int len=strlen(a);    for (int i=0; i<len; i++)    {        a[i]=tolower(a[i]);    }}int main(void){    char a[1000010]={0},b[]="doge";    getnext("doge",nextval);    int cntt=0;    while (gets(a)!=NULL)    {            change(a);                cntt+=sea(a,b);        memset(a,0,sizeof(a));    }    printf("%d\n",cntt);    return 0;}

第二种:求子串出现个数,比如abababa    aba  要是按第一种求法,这个答案会是2,但出现次数不是个数,因此答案是3。例题为POJ 3461

代码:

#include<iostream>#include<algorithm>#include<cstdlib>#include<sstream>#include<cstring>#include<cstdio>#include<string>#include<deque>#include<cmath>#include<queue>#include<set>#include<map>using namespace std;typedef long long LL;int nextval[101010];void getnext(char s[],int nextval[]){int j=0,k=-1;nextval[0]=-1;int lenp=strlen(s);while(j!=lenp)  //{if(k==-1||s[j]==s[k])nextval[++j]=++k;  //elsek=nextval[k];}}int sea(char s[],char t[]){int cnt=0;int i=0,j=0;int la=strlen(s),lb=strlen(t);while (i<la&&j<lb){if(j==-1||s[i]==t[j]){i++;j++;}elsej=nextval[j];if(j==lb){cnt++;j=nextval[j];}}return cnt;}int main(void){char a[1000010]={0},b[1000010]={0};int tcase;scanf("%d",&tcase);while (tcase--){memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(nextval,0,sizeof(nextval));scanf("%s%s",b,a);getnext(b,nextval);printf("%d\n",sea(a,b));}return 0;}

至于为什么可以这么玩,让我补完作业再慢慢研究  

0 0
原创粉丝点击