HihoCoder第三周:

输入

第一行一个整数N,表示测试数据组数。

接下来的N*2行,每两行表示一个测试数据。在每一个测试数据中,第一行为模式串,由不超过10^4个大写字母组成,第二行为原串,由不超过10^6个大写字母组成。

其中N<=20

输出

对于每一个测试数据,按照它们在输入中出现的顺序输出一行Ans,表示模式串在原串中出现的次数。

样例输入

5

HA

HAHAHA

WQN

WQN

ADA

ADADADA

BABABB

BABABABABABABABABB

DAD

ADDAADAADDAAADAAD

样例输出

3

1

3

1

0

KMP于我的理解就是通过记录已经匹配的字符的情况,防止不必要的匹配。记录已经匹配字符的单元实际就是next数组,我其实觉得想法非常巧妙的一点在于,模式串与原串匹配,正常来讲总是会想跟原串或许会有什么关系,因为要记录已经匹配的字符嘛。但是相反,next只是跟模式串有关,原理就在于

如果一个字符串满足这个条件:有一个整数k,使得

p0 p1 ...pk-1 pk = pj-k pj-k+1...pj-1 pj

这样我下一次匹配不成功的时候,原串中的j就不用回溯,模式串中的i=next[i],因为你本身是满足这个条件的,所以当moshi[i]不相等的时候,我就不用从第0个字符从头开始试是否相等,而只需从moshi[next[i]]开始匹配即可。

next数组就是记录这个字符之前有多少字符和整个字符串最开始的相应的字符相等的。

之后就是如何求next数组。

求的时候本身就可以用递归来求:

如果moshi[i]==moshi[j]

那么i++;

j++;

moshi[j]= i;这里i代表从头开始的前缀,j代表后缀

如果不相等

那么i=next[i];

代码:

#include <iostream>
#include <cstring>
using namespace std; char moshi[10004],yuanchuan[1000004];
int calnext[1000004]; void Calnext(int len1)
{
memset(calnext,0,1000004*sizeof(int)); calnext[0]=-1; int i,j=-1; for(i=0;i<len1+1;)
{
if(moshi[i]==moshi[j]||j==-1)
{
i++;
j++;
if(moshi[i]==moshi[j])//calnext[i]==calnext[j]
{
calnext[i]=calnext[j];
}
else
{
calnext[i]=j;
}
}
else
{
j=calnext[j];
}
}
} int Cal(int len1,int len2)
{
int result=0;
int i=0,j=0;
//仔细想一下,j其实是一直往前走的!!!!!它没有回去的时候!!!!
while(i<len1&&j<len2)
{
if(moshi[i]==yuanchuan[j])
{
i++;
j++;
}
else
{
if(calnext[i]==-1)
{
i=0;
j++;
}
else
{
i=calnext[i];
}
}
if(i>=len1)
{
result++;
i=calnext[len1];
}
}
return result;
} int main()
{
int count;
cin>>count; while(count--)
{
cin>>moshi;
cin>>yuanchuan; int len1 = strlen(moshi);
int len2 = strlen(yuanchuan); Calnext(len1); cout<<Cal(len1,len2)<<endl; } return 0;
}

之前遇到的两个问题都在注释中了,一个是改进求解next数组时,应该是判断moshi是否相等,而跟next没什么关系。

比方说在匹配abc,c处错误,可能就跳到之前abd处,你只需判断c和d是否相等,如果相等了,说明这里不用再记录d的位置了,记录d如果不相等时会跳到哪里吧,可能是再之前的abf处。如果按照我之前的想法简直就解释不了了,abc,匹配c时出问题,跳转到abd处,你判断d可能会跳到f处,这里,然后你把c也弄到f哪里根本解释不同。(这里仅仅为我错误又很缥缈的思路。。。。)

第二个就是我受了暴力搜索的影响,其实看别人写的暴力,也是就一个循环,原串中的j也是不用回溯的,用一个k表示就好,不相等的话k置成0即可。我还弄了两层循环,好不麻烦。结果就是写了next数组之后还是两层循环,还是timelimited。真是。。。。在kmp算法中,j只是会一味的往前走,不能回头。所以一层循环,所以时间复杂度就是O(m+n)。

POJ2406:

Description

Given two strings a and b we define a*b to be theirconcatenation. For example, if a = "abc" and b = "def" thena*b = "abcdef". If we think of concatenation as multiplication,exponentiation by a non-negative integer is defined in
the normal way: a^0 ="" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string ofprintable characters. The length of s will be at least 1 and will not exceed 1million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n forsome string a.

Sample Input

abcd

aaaa

ababab

.

Sample Output

1

4

3

代码:

#include <iostream>
#include <cstring>
using namespace std; char moshi[1000004];
int calnext[1000004]; void Calnext(int len1)
{
memset(calnext,0,1000004*sizeof(int)); calnext[0]=-1; int i,j=-1; for(i=0;i<len1;)
{
if(moshi[i]==moshi[j]||j==-1)
{
i++;
j++;
calnext[i]=j;
}
else
{
j=calnext[j];
}
}
} int main()
{
while(true)
{
scanf("%s",moshi); if(strcmp(moshi, "."))
{
int len1 = strlen(moshi); Calnext(len1); if(len1%(len1-calnext[len1])==0)
{
cout<<len1/(len1-calnext[len1])<<endl;
}
else
{
cout<<'1'<<endl;
} }
else
break; } system("pause");
return 0;
}

POJ2406这道题有意思的地方在于求next[len1],想一想就是abcabc#,如果#这里不匹配的话会跳转到a那里,即是位置3。如果是abdab#,会跳转到d那里,即是位置2。

所以我的理解就是当next[len1]这个值如果大于等于一半的len1的话,那么这个字符串就是powerstring。而如何把单元重复的长度求出来,就是len1-next[len1](试想一下abcabcabcabc#这样的字符串,它会记录的是最大的k是9,即前缀和后缀重叠了的是9,所以未重叠部分其实就是单位的abc,所以有多少个abc呢,结果就是 除以就好了。)

小弟弱傻痴菜,还望路人多多指正,互相交流。

版权声明:本文为博主原创文章,未经博主允许不得转载。

HihoCoder第三周与POJ2406:KMP算法总结的更多相关文章

  1. POJ2406 KMP算法

    POJ2406 问题重述:给定字符串s0,记连续的k个s前后相连组成的s0s0...s0为s0^k.输入字符串S,求最大的k,使得S = s0^k. 问题分析: 1.采用kmp算法求出前缀函数 pre ...

  2. poj2406(kmp算法)

    Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc&quo ...

  3. 【算法•日更•第三十一期】KMP算法

    ▎前言 这次要讲的HMP算法KMP算法很简单,是用于处理字符串的,之前一直以为很难,其实也不过如此(说白了就是优化一下暴力). ▎处理的问题 通常处理的问题是这样的:给定两个字符串s1和s2,其中s1 ...

  4. POJ2406 kmp算法next数组-串的最小循环节/循环周期

    题目链接:http://poj.org/problem?id=2406 题目大意:问给出的字符串最多由多少个子串相乘得来的. 思路:利用next数组的含义来解. 1.一个串的最小循环节长度:len - ...

  5. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  6. 算法起步之kmp算法

    [作者Idlear  博客:http://blog.csdn.net/idlear/article/details/19555905]            这估计是算法连载文章的最后几篇了,马上就要 ...

  7. KMP算法的时间复杂度与next数组分析

    一.什么是 KMP 算法 KMP 算法是一种改进的字符串匹配算法,用于判断一个字符串是否是另一个字符串的子串 二.KMP 算法的时间复杂度 O(m+n) 三.Next 数组 - KMP 算法的核心 K ...

  8. hihoCoder #1015 : KMP算法【KMP裸题,板子】

    #1015 : KMP算法 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在 ...

  9. hihoCoder 1015 KMP算法(kmp)

    #1015 : KMP算法 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣.他们约定好互相帮助 ...

随机推荐

  1. 第三节:Vuejs常用特性2和图书案例

    一. 常用特性2 1. 监听器 用watch来响应数据的变化, 一般用于异步或者开销较大的操作, watch 中的属性 一定是data 中 已经存在的数据!!! 当需要监听一个对象的改变时,普通的wa ...

  2. Dart语言学习(十) Dart流程控制语句

    一.条件语句:if.if...elseif.if...elseif...else int score = 95; if (score >=90) { print('优秀'); } else if ...

  3. Python实现图片识别加翻译【高薪必学】

    Python使用百度AI接口实现图片识别加翻译 另外很多人在学习Python的过程中,往往因为没有好的教程或者没人指导从而导致自己容易放弃,为此我建了个Python交流.裙 :一久武其而而流一思(数字 ...

  4. AT指令之 TCP/IP 命令

    BC26 还有一组专用于 TCP 通信的 AT 指令:<BC26_TCP/IP_AT_Commands_Manual_V1.1>,之前已经有了 Socket 可以进行 TCP 通信,现在又 ...

  5. 7 JavaScript函数调用&this关键字&全局对象&函数调用&闭包

    JavaScript函数有4种调用方式,每种方式的不同之处在于this的初始化 一般而言,在JavaScript中,this指向函数执行时的当前对象 如果函数不属于任何对象,那么默认为全局对象,即HT ...

  6. 2 Struts2的执行流程&配置文件的加载顺序

    执行流程: 访问前段页面,通过url访问action 访问xml中Struts2核心过滤器,并执行一组拦截器(这组拦截器在struts-default.xml中,实现了部分功能) 通过action配置 ...

  7. Linux环境查看Java应用消耗资源情况

    linux线上资源耗时定位 https://www.cnblogs.com/wuchanming/p/7766994.html 1. jps -ml 查看服务器上运行的Java程序 2. jmap 查 ...

  8. 【PAT甲级】1009 Product of Polynomials (25 分)

    题意: 给出两个多项式,计算两个多项式的积,并以指数从大到小输出多项式的指数个数,指数和系数. trick: 这道题数据未知,导致测试的时候发现不了问题所在. 用set统计非零项时,通过set.siz ...

  9. C/C++ - CallBack

    这是实验楼上一个callback debug例子,我没有提交结果,但在本地上运行没有任何问题,也无警告: #include <stdio.h> #define MAX 3 typedef ...

  10. CSP2019 括号树

    Description: 给定括号树,每个节点都是 ( 或 ) ,定义节点的权值为根到该节点的简单路径所构成的括号序列中不同合法子串的个数(子串需要连续,子串所在的位置不同即为不同.)与节点编号的乘积 ...