吃透烤馍片算法

kmp又称烤(k)馍(m)片(p)算法,实际上是通过模式串本身的特性来优化模式串的匹配

next[j]表示j之前的字符串中有长度为next[j]的相同前缀后缀

失配时移动位置=失配字符所在位置-失配字符对应的next值,即j-next[j]

next[0]=-1 表示当0位置失配时,要将字符串向右移1位

1.求next数组:

next[j]表示j之前的字符串中有长度为next[j]的相同前缀后缀

求next数组的过程相当于模式串自己和自己匹配

void getNext()
{
    int i,j;
    i=0;j=-1;next[0]=-1;
    while(i<tlen)
    {
        if(j==-1||t[i]==t[j])next[++i]=++j;
        else j=next[j];
    }
}

2.用next数组求最小循环节的长度:

如果一个字符串可以由k个某一子串组成,那么 这个字符串的最小循环节为该子串,循环周期为k。

如abcd最小循环节为abcd,abcabc最小循环节为abc

怎样求最小循环节?   如abcabcabc

next数组为:

a   b   c   a   b   c   a   b   c     
0 1 2 3 4 5 6 7 8 9
-1 0 0 0 1 2 3 4 5 6

next[len]是一个很特殊的值,它表示整个字符串前后缀相同的最大长度

如上栗子,next[len]=6

说明 字符串中 a[0]-a[5] 与 a[3]-a[8]是完全相同的

也就是说 a[0]-a[2]与 a[3]-a[5]是完全相同的,a[3]-a[5] 与 a[6]-a[8]是完全相同的,

也就是说该字符串可以由 a[0]-a[2]循环3次组成

所以只要tlen%(tlen-next[tlen])==0&&next[tlen]!=0 字符串就可以由长度比它小的子串组成

否则循环节为它本身

while(~scanf("%s",t))
{
    tlen=strlen(t);
    getNext();
    if(tlen%(tlen-next[tlen])==0&&next[tlen]!=0)printf("%d\n",tlen-next[tlen]);
    else printf("%d\n",tlen);
}

3.kmp求模式串第一次出现的位置

int kmp_Index()
{
    int i=0,j=0;
    getNext();
    while(i<slen&&j<tlen)
    {
        if(j==-1||s[i]==t[j])
        {
            i++;
            j++;
        }
        else j=next[j];
    }
    if(j==tlen)return i-tlen;
    else return -1;
}

4.kmp求模式串在匹配串中出现的次数(有可重叠和不可重叠之分)

int kmp_Count()
{
    int ans=0;
    int i,j=0;
    if(slen==1&&tlen==1)
    {
        if(s[0]==t[0])return 1;
        else return 0;
    }
    getNext();
    for(i=0;i<slen;i++)
    {
        while(j>0&&s[i]!=t[j])j=next[j];
        if(s[i]==t[j])j++;
        if(j==tlen)
        {
            ans++;
            j=0;
            //如果子串可以重叠j=next[j];
        }

    }
    return ans;
}

烤(k)馍(m)片(p)完整模板:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define N 1000010
using  namespace std;
int next[N];
char s[N],t[N];
int slen,tlen;
void getNext()
{
    int j,k;
    j=0;k=-1;next[0]=-1;
    while(j<tlen)
    {
        if(k==-1||t[j]==t[k])next[++j]=++k;
        else k=next[k];
    }
}
//返回模式串t在主串s中首次出现的位置
int kmp_Index()
{
    int i=0,j=0;
    getNext();
    while(i<slen&&j<tlen)
    {
        if(j==-1||s[i]==t[j])
        {
            i++;
            j++;
        }
        else j=next[j];
    }
    if(j==tlen)return i-tlen;
    else return -1;
}
//返回模式串t在主串s中出现的次数
int kmp_Count()
{
    int ans=0;
    int i,j=0;
    if(slen==1&&tlen==1)
    {
        if(s[0]==t[0])return 1;
        else return 0;
    }
    getNext();
    for(i=0;i<slen;i++)
    {
    //    printf("***%d %d\n",i,j);
        while(j>0&&s[i]!=t[j])j=next[j];
        if(s[i]==t[j])j++;
        if(j==tlen)
        {
            ans++;
            j=0;
            //如果子串可以重叠j=next[j];
        }

    }
    return ans;
}

int main()
{
    //用next数组求循环节的长度
     while(~scanf("%s",t))
    {
        tlen=strlen(t);
        getNext();
       // for(int i=0;i<=tlen;i++)printf("%d %d\n",i,next[i]);
        if(tlen%(tlen-next[tlen])==0&&next[tlen]!=0)printf("%d\n",tlen-next[tlen]);
        else printf("%d\n",tlen);
    }
/*
  //kmp模式匹配
    while(~scanf("%s%s",s,t))
    {
        slen=strlen(s);
        tlen=strlen(t);
      //  printf("%d\n",kmp_Index());
        printf("%d\n",kmp_Count());
      //  for(int i=0;i<=tlen;i++)printf("%d %d\n",i,next[i]);
    }
*/
    return 0;
}

时间: 2024-08-29 19:27:04

吃透烤馍片算法的相关文章

【NOIP模拟赛】lover——心上人

心上人 [问题描述]  人到初三,总会遇到情感问题,比方说小 J 就喜欢上了小 W.于是小 J 就需要说一长串的话讨小 W 欢心.现在已知小 W 听到一些词就会很高兴,而且白听不厌,但她又讨厌小 J 说的话的长度短于或长于她所期望的.所以小 J 只能说一个长度为 L 的字符 串,并使小 W 喜欢的词在其中出现的次数尽量多.小 J 想请你告诉他,一个长度为 L 的字符串中最多出现小 W 喜欢的话多少次... [输入格式]   输入共 2 行. 第 1 行包含 1 个正整数 L,表示 小 J 需要的

如何系统地学习数据挖掘

数据挖掘:What?Why?How?这个问题思考了很久,作为过来人谈一谈,建议先看下以前的一些回答. 什么是数据挖掘? 怎么培养数据分析的能力? 如何成为一名数据科学家? 磨刀不误砍柴工.在学习数据挖掘之前应该明白几点: 数据挖掘目前在中国的尚未流行开,犹如屠龙之技. 数据初期的准备通常占整个数据挖掘项目工作量的70%左右. 数据挖掘本身融合了统计学.数据库和机器学习等学科,并不是新的技术. 数据挖掘技术更适合业务人员学习(相比技术人员学习业务来的更高效) 数据挖掘适用于传统的BI(报表.OLA

如何系统地学习数据挖掘?

看数据挖掘方面的算法理论时经常感觉一些公式的推导过程如天书一般,例如看svm的数学证明,EM算法..,感觉知识跳跃比较大,那么数据挖掘系统的学习过程是怎么样? 磨刀不误砍柴工.在学习数据挖掘之前应该明白几点: 数据挖掘目前在中国的尚未流行开,犹如屠龙之技. 数据初期的准备通常占整个数据挖掘项目工作量的70%左右. 数据挖掘本身融合了统计学.数据库和机器学习等学科,并不是新的技术. 数据挖掘技术更适合业务人员学习(相比技术人员学习业务来的更高效) 数据挖掘适用于传统的BI(报表.OLAP等)无法支

算法笔记_001:斐波那契数的多种解法

本篇文章解决的问题来源于算法设计与分析课程的课堂作业,主要是运用多种方法来计算斐波那契数.具体问题及解法如下: 一.问题1: 问题描述:利用迭代算法寻找不超过编程环境能够支持的最大整数的斐波那契数是第几个斐波那契数.(Java: 231-1 for int, 263-1 for long) 解决方案:针对问题1,此处要使用迭代法来解决,具体实现代码如下: //用迭代法寻找编程环境支持的最大整数(int型)的斐波那契数是第几个斐波那契数 public static int max_int_iter

面试高级算法梳理笔记

面试高级算法梳理笔记 1.1 说明 本篇为<挑战程序设计竞赛(第2版)>读书笔记系列,旨在: 梳理算法逻辑 探索优化思路 深入代码细节 1.2 目录 原文首发于个人博客Jennica.Space,按算法难度划分为初中高三个级别,详细目录及链接如下: 初级篇 穷竭搜索 贪心 动态规划 数据结构 图论 数论 中级篇 二分搜索 常用技巧 数据结构(二) 动态规划(二) 网络流 计算几何 高级篇 数论(二) 博弈论 图论(二) 常用技巧(二) 智慧搜索 分治 字符串 1.3 题解 配套习题及详解同步发

排序算法—冒泡排序

*/--> 排序算法-冒泡排序 Table of Contents 1 问题描述 2 冒泡排序(Bubble) 2.1 冒泡排序(一) 2.2 冒泡排序(二) 2.3 冒泡排序(三) 2.4 冒泡排序(四) 3 阅读参考 1 问题描述 引子 排序是数据结构中十分重要的一章,排序算法有很多种,一直没时间整理而且很多排序算法理解的也不是很透彻.希望通过这次整理吃透吧! 排序算法十分多,故分篇进行整理. 说明 本文重点是理解排序算法,而不是完整的程序,所以每节都只有具体排序算法的接口.没有完整的源代码

GeekBand-极客班-C++算法原理与实践-董飞-课程笔记(一)

GeekBand-极客班-C++算法原理与实践-董飞-课程笔记(一) 算法入门和编程风格 从一道入门题谈起 /*StrStr Returns the position of the first occurrence of string get in string source, or -1 if target is not part not of source. */ 另一篇博客:http://blog.csdn.net/lionpku/article/details/46713877 StrS

算法和面试

因为去年坑爹的创业失败了,所以在年底就预备开始找工作.对于公司我最看重Google,13年底面过一次,挂得十分惨烈,这次正好有时间,就打算好好准备一下.面试的核心在于算法,对于Google尤为如此.刷题是不用说的了,我的leetcode注册了两三个账号,刷了七八遍,脑子都刷糊了,当然受益也不少,还有geekforgeeks作为补充,只要把这两个吃透,基本上所有的面试都可以轻松拿下. 在经过了三个多月的精心准备,年后我信心满满的从家里回到北京的住处,与Google的HR约好面试时间,然后就是电话面

算法生成七芒星

玄幻小说中经常会有七芒星的技法,这一节就使用算法生成下七芒星的图像.在西方,7被认为是一个很有魔力的数字.上帝用7天造人,第7天休息:圣经启示录中有7封印.7灯台.7号角等等.但是魔法符号中却很少见到七芒星.不过在神秘学上,七芒星阵是存在的,他蕴含着非常强大的力量,无数的人都在寻觅并探索着他,但是七芒星的强大,使得很多人都未能解开它的神秘面纱,这让七芒星至今都成为了一种迷. 关于七芒星的资料:       1 .七芒星很难被准确地画出,因为七芒星是“不平均却稳定的一体”.完美的七芒星是很漂亮的图