• hdu 1686 & poj 2406 & poj 2752 (KMP入门三弹连发)


    首先第一题

    戳我穿越;http://acm.hdu.edu.cn/showproblem.php?pid=1686

    题目大意好理解,每组输入一个子串和一个母串,问在母串中有多少个子串?

    文明人不要暴力,因为宽度会超时,除去暴力后这就是赤果果的KMP

    KMP的重点在于在子串中建立一个匹配表,记录 到每一位的 前缀后缀 中的相同的子子串的最大长度

    然后在比较子母串的时候当遇到不同时 后移的位数就是前面相同的个数减去对应的匹配表例的数

    额 讲的不清不楚 那推荐戳这里:http://kb.cnblogs.com/page/176818/

    那这题就是个裸的KMP模板

    code 还是很简单的

    #include<cstdio>
    #include<cstring>
    using namespace std;
    char cword[10001];
    int num[10001];
    char mword[1000001];
    int main()
    {
        int t,sum,i,x,j,y;
        char temp;
        while (~scanf("%d",&t))
        {
            while (t--)
            {
                sum=0;
                j=-1;i=0;
                num[0]=-1;
                scanf("%s",cword);
                scanf("%s",mword);
                x=strlen(cword);
                y=strlen(mword);
                while (i<x) //num数组就是用来储存匹配表
                {
                    if (j==-1||cword[i]==cword[j])
                    {
                        j++;
                        i++;
                        if (cword[i]!=cword[j])
                            num[i]=j;
                        else
                            num[i]=num[j];
                    }
                    else
                       j=num[j];
                }
                i=0;j=0;
                while (i<y)
                {
                    if (j==-1||mword[i]==cword[j])
                    {
                        i++;
                        j++;
                    }
                    else
                        j=num[j];
                    if (j==x)
                    {
                        sum++;
                        j=num[j];
                    }
                }
                printf("%d
    ",sum);
            }
        }
        return 0;
    }
    

    第二题 :pid=124http://acm.hdu.edu.cn/showproblem.php?7

    输出一个单词里最多是由多少个子串重复连接而成 注意 是重复 连接 而成,如abefab因为ab没有连接,所以应该输出1

    也是kmp的应用,考虑有特殊情况

    code更短

    #include<cstdio>
    #include<cstring>
    using namespace std;
    char yj[1000001];
    int jjc[1000001];
    int main()
    {
        int i,j,x,n;
        while (~scanf("%s",yj))
        {
            if (yj[0]=='.')
                break;
            j=-1;
            jjc[0]=-1;
            x=strlen(yj);
            for (i=0;i<x;)
            {
                if (j==-1||yj[i]==yj[j]) jjc[++i]=++j;
                else j=jjc[j];
            }
            if (x%(x-jjc[x])==0)
                printf("%d
    ",x/(x-jjc[x]));
            else
                printf("1
    ");
        }
        return 0;
    }
    

    第三题:http://poj.org/problem?id=2752

    就是找出一行名字中在前缀后缀中都存在的字串的长度,升序输出

    对num数组匹配表的运用,既然在前缀后缀中都存在,那么其字串的最后一个字母必定和整个串的最后一位相同

    然后再利用num数组一直向下滚一边

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    char yj[400001];
    int num[400001];
    int jjc[400001];
    int main()
    {
        int i,j,x,t,k;
        while (~scanf("%s",yj))
        {
            j=-1;i=0;
            num[0]=-1;
            x=strlen(yj);
            while (i<x)
            {
                if (j==-1||yj[i]==yj[j])
                    num[++i]=++j;
                else
                    j=num[j];
            }
            t=num[x-1];
            k=0;
            while (t!=-1)
            {
                if (yj[t]==yj[x-1])
                    jjc[k++]=t+1;
                t=num[t];
            }
            for (i=k-1;i>=0;i--)
                printf("%d ",jjc[i]);
            printf("%d
    ",x);
        }
        return 0;
    }
    

      

      

  • 相关阅读:
    【JZOJ3360】【NOI2013模拟】苹果树
    【SDOI2009】【BZOJ1878】HH的项链
    【JZOJ3234】阴阳
    【BZOJ3482】【JZOJ3238】[COCI2013]hiperprostor 超空间旅行
    【JZOJ3348】【NOI2013模拟】秘密任务 (Standard IO) (最小割唯一性的判定)
    【JZOJ4665】【CF407E】k-d-sequence
    【SHTSC2013】阶乘字符串
    【SHTSC2013】超级跳马
    半平面交笔记
    转:Why SeaJS
  • 原文地址:https://www.cnblogs.com/JJCHEHEDA/p/4690262.html
Copyright © 2020-2023  润新知