kmp算法一点合集

第一题 hdu 1711 Number Sequence

题意:就是匹配看在不在。

第二题 hdu 1686 oulipo

点击打开hdu 1686

思路:

1 题目要求的是给定一个模式串个一个文本串,求出模式串在文本串中出现几次

第三题 hdu 2087 剪花布条

点击打开hdu 2087

思路:

1 题目要求的是给定一个文本串和给定一个模式串,求文本串中有几个模式串。
2 注意文本串为”aaaaaa”,模式串”aa”的时候,ans = 3 而不是5。(与上面一题不同)

第四题 hdu 3746 Cyclic Nacklace

点击打开hdu 3746

思路:(最小循环节个数+注意当为abcd的时候。。

1 题目要求的是给定一个字符串,问我们还需要添加几个字符可以构成一个由n个循环节组成的字符串。
2 可知我们应该先求出字符串的最小循环节的长度:假设字符串的长度为len,那么最小的循环节就是cir = len-next[len] ; 如果有len%cir == 0,那么这个字符串就是已经是完美的字符串,不用添加任何字符;如果不是完美的那么需要添加的字符数就是cir - (len-(len/cir)*cir)),相当与需要在最后一个循环节上面添加几个。
3 如果cir = 1,说明字符串只有一种字符例如“aaa” ; 如果cir = m说明最小的循环节长度为m,那么至少还需m个;

如果m%cir == 0,说明已经不用添加了

点击查看代码

第五题 hdu 1358 Period

点击打开hdu 1358

思路:

1 题目要求的是给定一个长度为n的字符串,求出字符串的所有前缀字符串中该字符串刚好由k个最小循环节够成,由于题目要求k最大那么就是这个循环节最小
2 只要先求出next数组,然后去枚举所有的前缀找到满足的输出长度和k注意当为abcd的时候。。

点击查看代码

第六题 hdu 2203 亲和串

点击打开hdu 2203

思路:

1 题目要求的是给定字符串s1 和 s2,问s1能否通过移位得到使得s2包含在s1里面。
2 很显然的kmp的模板题,只须在s1后面在添上一个s1即可。这里特别注意strcat的使用

第七题 hust 1010 The Minimum Length

点击打开hust 1010

思路:

1 题目要求的是,有一个字串A,现在利用A组成了一个新的字符串AAAAA…,现在从这个新的字符串的两个不同位置剪下去得到字符串B,问A的最小长度
2 由于B里面的字符都是来自A,那么如果要A最小那么最小值就是等于B的最小循环节。
3 直接对B求最小循环节(比如baaabbba, 答案也是6,说明

baaabbba

    baaabbba  中baaabb就是最小循环节

第八题 poj 2406 Power Strings

点击打开poj 2406

思路:

1 题目要求的是给定一个字符串找到最小循环节的个数,但是这里有个限制的地方就是如果这个字符串

不是刚好由n个最小循环节组成那么就认为一整串才是一个循环节(这个地方对于不同的题目不同)

2 题目说了输入的字符是可打印的,所以应该用gets读入,判断终止的时候用strcmp。

点击查看代码


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
const int maxn=1e6+5;
char a[maxn];
int nxt[maxn];
void getnxt(){
    int k=-1;
    int j=0;
    nxt[0]=-1;
    int len=strlen(a);
    while(j<len){
        if(k==-1||a[k]==a[j]){
            k++;
            j++;
            nxt[j]=k;
        }
        else k=nxt[k];
    }
}
void init(){
    //memset(dp,0,sizeof(dp));
    memset(nxt,0,sizeof(nxt));
}
int main(){
    int n;
    int cnt=0;
    while(~scanf("%d",&n)&&n!=0){
        init();
        scanf("%s",&a);
        getnxt();
        printf("Test case #%d\n",++cnt);
        for(int i=2;i<=n;++i){
            int cir=i-nxt[i];
            if(cir==1)printf("%d %d\n",i,i);//
            else if(cir!=i&&i%cir==0){//自己这些地方太简陋了导致错误
                    //如果cir=i,那么就是他自己没有循环节的。比如asdf,我原本的结果也会输出
                cout<<i<<' '<<i/cir<<'\n';
            }
            else continue;
        }
        cout<<'\n';

    }


}
原本代码:
        int cir=i-nxt[i];
            if(i%cir==0){
                cout<<i<<' '<<i/cir<<'\n';
            }
            else continue;

思路:

1 题目要求的是给定字符串s1 和 s2,问s1能否通过移位得到使得s2包含在s1里面。
2 很显然的kmp的模板题,只须在s1后面在添上一个s1即可。(我居然没有想到。。)这里特别注意strcat的使用
3 strcat函数,函数的原行strcat(char *s , char *p);注意这里的s和p所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串;所以假设s = “abc”,现在想得到“abcabc”那么不能直接的strcat(s , s),而是先用一个tmp数组存储s,即strcpy(tmp , s , sizeof(s)) , 然后在strcat(s , tmp);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值