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\n",sum);
        }
    }
    return 0;
}

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

输出一个单词里字串的个数

也是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;
}

  

  

时间: 2024-08-07 06:11:16

hdu 1686 & poj 2406 & poj 2752 (KMP入门三弹连发)的相关文章

poj 2406 Power Strings KMP匹配

对于数组s[0~n-1],计算next[0~n](多计算一位). 考虑next[n],假设t=n-next[n],如果n%t==0,则t就是问题的解,否则解为1. 这样考虑: 比如字符串"abababab", a  b a b a b a b * next     -1 0 1 2 3 4 5 6  7 考虑这样的模式匹配,将"abababab#"当做主串,"abababab*"当做模式串,于是进行匹配到n(n=8)时,出现了不匹配: 主串   

POJ 2406 Power Strings KMP运用题解

本题是计算一个字符串能完整分成多少一模一样的子字符串. 原来是使用KMP的next数组计算出来的,一直都觉得是可以利用next数组的,但是自己想了很久没能这么简洁地总结出来,也只能查查他人代码才恍然大悟,原来可以这么简单地区求一个周期字符串的最小周期的. 有某些大牛建议说不应该参考代码或者解题报告,但是这些大牛却没有给出更加有效的学习方法,比如不懂KMP,难倒不应该去看?要自己想出KMP来吗?我看不太可能有哪位大牛可以直接自己"重新创造出KMP"来吧. 好吧,不说"创造KMP

poj 2406 Power Strings(KMP&amp;思维)

Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 31093   Accepted: 12974 Description Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "

HDU 4300 Clairewd‘s message 拓展KMP入门

HDU 4300 Clairewd's message 拓展KMP入门 题意 原题链接 这个题关键是要读懂题意,我做的时候就没有读懂,泪.题意是说给你的一个两个字符串,一个是26个字母密码表,依次对应替换的字母.然后给你一个字符串,这个字符串是不完整的(完整的应该是前半部分是加密的,后半部分是解密了的),然而,给你的字符串一定是加密的部分+一部分解密的部分(可以是全部,也可以是没有),让你求出最短的完整字符串,包括密文和明文: 解题思路 考虑给出的字符串S加密部分一定全部给出,所以给出的字符串的

poj 2406 Power Strings(kmp的nxt数组找最小循环节)

题目链接:poj 2406 Power Strings 题意: 给你一个字符串,让你找出这个字符串的最大循环次数,及最小循环节. 题解: 用kmp的nxt数组搞搞,L=j-nxt[j],为前缀j的最小循环节. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define F(i,a,b) for(int i=(a);i<=(b);++i) 5 using namespace std;

SPOJ SUBST1 POJ 2406 POJ REPEATS 后缀数组小结

//聪神说:做完了题目记得总结,方便以后复习. SPOJ SUBST1 题目链接:点击打开链接 题意:给一个字符串,求不同子串个数. 思路:假设所有子串都不同,答案为len*(len+1)/2;然而不是这样... 下面我们就找出重复的子串: 首先先将后缀排序,对于后缀i能生成len-sa[i]个子串,这其中有height[i]个子串与第i-1个后缀生成的子串重复了: 所以答案为 len*(len+1)/2-segema(height[i]) . cpp代码: //spoj disubstr #i

题解报告:hdu 2087 剪花布条(KMP入门)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 Problem Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input 输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样.花纹条和小饰条不会超过1000个字符长.如果遇见#字符

POJ - 2406 Power Strings (KMP循环节)

Description Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative inte

poj 2406 Power Srings (kmp循环节) (经典)

<题目链接> 题目大意: 给出一个字符串,求其字串在该字符串中循环的最大周期. 解题分析: length=len-Next[len],len为该字符串的最小循环节,如果len%length==0,那么周期就为len/lenght,如果不能整除,则说明该字符串的字串不具有周期性,输出1. KMP最小循环节的证明 >>> #include <cstdio> #include <cstring> const int maxn = 1000000 + 100;