首先第一题

戳我穿越;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\n",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\n",x/(x-jjc[x]));
        else
            printf("1\n");
    }
    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\n",x);
    }
    return 0;
}

  

  

posted on 2015-07-30 18:36  蜘蛛侦探  阅读(238)  评论(0编辑  收藏  举报