• 两种KMP题+KMP模版整理


    最近稍微看了下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])
            {
                j++;
                k++;
                next[j]=next[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=nextval[j];            
            }    
        }
        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])
            {
                k++;
                j++;
                nextval[j]=nextval[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=nextval[j];            
            }    
        }
        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
    ",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;  //
    		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=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
    ",sea(a,b));				
    	}
    	return 0;
    }
    

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

  • 相关阅读:
    HDU 4832(DP+计数问题)
    mongodb安装与使用
    (hdu step 6.3.7)Cat vs. Dog(当施工方规则:建边当观众和其他观众最喜爱的东西冲突,求最大独立集)
    dba_dependencies查询结果视图
    情绪一点点
    c#基于这些,你已经看到了?(一)-----谁才刚刚开始学习使用
    九. 200创业教训万元获得--“神刻”这是忽悠?
    初步swift语言学习笔记6(ARC-自己主动引用计数,内存管理)
    采用CSS3 Media Query技术适应Android平板屏幕分辨率和屏幕像素密度
    线程的上下文
  • 原文地址:https://www.cnblogs.com/Blackops/p/5400755.html
Copyright © 2020-2023  润新知