kmp入门小结

void get_next(char *s)
{
    int len = strlen(s);
    int j = 0; int k = -1;
    while (j < len){
        if (k == -1 || s[j] == s[k]){
            j++; k++; next[j] = k;
        }
        else k = next[k];
    }
}

设t = next[i]; next[i] 表示的是 i之前最大的t满足 s[0...t-1]  =  s[i-t...i-1]

比如 0123 4 0123 5 ,next[9] = 4.

结论:len - next[len] 为最小覆盖子串。

Poj3461 Oulipo

题意:给出两个串,问第二个串在第一个串中出现的次数

/* ***********************************************
     Author        : 一个西瓜
     Mail          : [email protected]
     Created Time  : 2015-04-07 16:24:21
    Problem       : Oulipo
************************************************ */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL; 

const int maxn = 11111;
int next[maxn];
char str[maxn];
char str1[maxn*100];

void get_next(char *s)
{
    next[0] = -1;
    int j = 0 ;int k = -1;
    int len = strlen(s);
    while(j<len){
        if(k==-1||s[j]==s[k]){
            j++;k++;next[j] = k;
        }
        else k = next[k];
    }
}

int gao(char *s1,char *s2)
{
    int ans = 0;
    int len1 = strlen(s1);int len2 =strlen(s2);
    int j = -1;int k = -1;
    while(j<len2){
        if(k==-1||s1[k]==s2[j]){
            j++;k++;
            //printf("%d %d\n",j,k);
        }
        else k = next[k];
        if(k==len1){
            ans++;k = next[k];
        }
    }
    return ans;
}

int main()
{
    int T;
    cin>>T;
    while(T--){
        cin>>str;
        cin>>str1;
        get_next(str);
        int k = gao(str,str1);
        cout<<k<<endl;
    }
    return 0;
}

Poj1961 Period

就用到上面那个结论了

/* ***********************************************
     Author        : 一个西瓜
     Mail          : [email protected]
     Created Time  : 2015-04-07 17:50:15
    Problem       : Period
************************************************ */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL; 

const int maxn = 1111111;
int next[maxn];
char str[maxn];
void get_next(char *s)
{
    int len =strlen(s);
    int j = 0;int k = -1;
    next[0] = -1;
    while(j<len){
        if(k==-1||s[j]==s[k]){
            j++;k++; next[j] = k;
        }
        else k = next[k];
    }
}

int main()
{
    int Icase = 0 ;
    int n;
    while(scanf("%d",&n)&&n){
        if(Icase) cout<<endl;
        printf("Test case #%d\n",++Icase);
        scanf("%s",str);
        get_next(str);
        int len = strlen(str);
        for(int i = 1;i<len;i++){
            int t = i+1;
            if(t%(t - next[t])==0&&(t/(t-next[t])!=1)){
                printf("%d %d\n",t,t/(t - next[t]));
            }
        }
    }
    return 0;
}

Poj2752 Seek the Name, Seek the Fame

给出一个串,问哪些既是前缀,又是后缀。

next数组不就是,到当前串的第i个位置,既是这个子串的前缀又是后缀的最长前缀么。迭代下去求就行了。

/* ***********************************************
     Author        : 一个西瓜
     Mail          : [email protected]
     Created Time  : 2015-04-07 17:28:12
    Problem       : Seek the Name, Seek the Fame
************************************************ */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL; 

const int maxn = 4*1e5 +10;
int next[maxn];
char str[maxn];

void get_next(char *s)
{
    next[0] = -1;
    int len =strlen(s);
    int j = 0 ;int k = -1;
    while(j<len){
        if(k==-1||s[j]==s[k]){
            j++;k++;next[j] =  k;
        }
        else k = next[k];
    }
}
vector<int> q;
int main()
{
    while(scanf("%s",str)!=EOF){
        get_next(str);
        q.clear();
        int k = strlen(str);
        q.push_back(k);
        k = next[k];
        while(k){
            q.push_back(k);
            k = next[k];
        }
        for(int i = q.size() - 1;i>=0;i--){
            printf("%d ",q[i]);
        }
        cout<<endl;
    }
    return 0;
}

Poj2406 Power Strings

和1961一样的。

/* ***********************************************
     Author        : 一个西瓜
     Mail          : [email protected]
     Created Time  : 2015-04-07 17:50:40
    Problem       : Power Strings
************************************************ */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL; 

const int maxn = 1e6+10;
char str[maxn];
int next[maxn];

void get_next(char *s)
{
    int len =strlen(s);
    int j = 0 ;int k = -1;
    next[0] = -1;
    while(j<len){
        if(k==-1||s[j]==s[k]){
            j++;k++; next[j] = k;
        }
        else k = next[k];
    }
}

int main() {
    while(cin>>str){
        if(str[0]==‘.‘) break;
        get_next(str);
        int len = strlen(str);
        if(len%(len-next[len])==0)
        cout<<len / (len - next[len])<<endl;
        else cout<<1<<endl;
    }
    return 0;
}

时间: 2024-11-01 00:59:21

kmp入门小结的相关文章

线段树入门小结

QUE:线段树? 称谓: 从刘汝佳的书中得知,"这种数据结构在学术界没有统一的术语,但线段树是最常见的叫法.其他叫法包括区间树(interval tree).范围树(range tree)等,但这些属于在特定的场合(如计算几何)中有着特殊的意义".怎么叫看读者的心情,以下统一用线段树称呼. 先来作一些了解: 线段树是一棵二叉树,它的左右儿子也都是一棵线段树.(定义) 线段树也叫区间树,为什么叫它区间树呢?因为线段树是一种基于区间的数据结构. 线段树的每个节点代表一个区间 [L,R],其

KMP入门

从头到尾彻底理解KMP 作者:July 时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进. 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP,思路混乱导致写也写得非常混乱,如此,留言也是"骂声"一片.所以一直想找机会重新写下KMP,但苦于一直以来对KMP的理解始终不够,故才迟迟没有修改本文. 然近期因在北京开了个算法班,专门讲解数据结构.面试.算法,才再次仔细回顾了这个KMP,在综合了一些网友的

mybatis入门小结(六)

入门小结---查询 1.1.1.1.1 #{}和${} #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入. #{}可以接收简单类型值或pojo属性值. 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称. ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型

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

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

KMP入门 博客推荐+模板+入门习题

KMP入门 入门介绍 KMP入门博客推荐 next数组讲解 模板代码 //这个是对next进行的优化 void getnext() //做的第一步是获得next[]的值 { int i=0,k=-1; next[0]=-1; while(i<lenb) { if(k==-1 || str[i]==str[k]) { i++; k++; if(t[i]==t[k]) next[i]=next[k]; else next[i]=k; } else k=next[k]; } } //没有带优化的部分

HDU 4300 Clairewd‘s message 拓展KMP入门

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

Tomcat和Servlet入门小结

Tomcat和Servlet入门小结 Tomcat入门 启动: 进入bin目录,双击startup.bat,运行该文件 访问浏览器,输入:http://localhost:8080 访问自己: ? 输入:http://别人的ip:8080 访问别人(8080为Tomcat的端口号) 启动时可能遇到的问题: 黑窗口一闪而过: *原因:没有正确配置JAVA_HOME变量: 启动报错: *暴力解决:在cmd中输入netstat -ano找到占用端口号的对应进程并杀死 *在Tomcat的config\s

KMP算法小结

今天又把KMP算法看了一遍,特此小结. 扯淡的话: KMP算法主要用来模式匹配.正如Implement strStr() 中形容的一样,“大海捞针”,当时看到题中变量如此命名,真的感觉实在是再贴切不过了. 在介绍KMP算法之前,先介绍一下BF算法,叫的这么暧昧(who is GF?),其实就是最low的暴力算法.这个男票略暴力. 事实上,JDK1.7中String的contains的源码用的就是BF算法.(1.7中调用了indexOf,我记得1.6中是直接写的contains接口来着) 截取了一

KMP入门(匹配)

Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], ...... , a[K + M - 1] = b[M].