HihoCoder第三周与POJ2406:KMP算法总结
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算法总结的更多相关文章
- POJ2406 KMP算法
POJ2406 问题重述:给定字符串s0,记连续的k个s前后相连组成的s0s0...s0为s0^k.输入字符串S,求最大的k,使得S = s0^k. 问题分析: 1.采用kmp算法求出前缀函数 pre ...
- poj2406(kmp算法)
Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc&quo ...
- 【算法•日更•第三十一期】KMP算法
▎前言 这次要讲的HMP算法KMP算法很简单,是用于处理字符串的,之前一直以为很难,其实也不过如此(说白了就是优化一下暴力). ▎处理的问题 通常处理的问题是这样的:给定两个字符串s1和s2,其中s1 ...
- POJ2406 kmp算法next数组-串的最小循环节/循环周期
题目链接:http://poj.org/problem?id=2406 题目大意:问给出的字符串最多由多少个子串相乘得来的. 思路:利用next数组的含义来解. 1.一个串的最小循环节长度:len - ...
- kmp算法详解
转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...
- 算法起步之kmp算法
[作者Idlear 博客:http://blog.csdn.net/idlear/article/details/19555905] 这估计是算法连载文章的最后几篇了,马上就要 ...
- KMP算法的时间复杂度与next数组分析
一.什么是 KMP 算法 KMP 算法是一种改进的字符串匹配算法,用于判断一个字符串是否是另一个字符串的子串 二.KMP 算法的时间复杂度 O(m+n) 三.Next 数组 - KMP 算法的核心 K ...
- hihoCoder #1015 : KMP算法【KMP裸题,板子】
#1015 : KMP算法 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在 ...
- hihoCoder 1015 KMP算法(kmp)
#1015 : KMP算法 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣.他们约定好互相帮助 ...
随机推荐
- sqllab less-1
1.访问sqllab 的less-1 按提示加入http://10.9.2.81/Less-1/?id=1 2. 后面加入单引号,发生报错http://10.9.2.81/Less-1/?id=1‘ ...
- spark实验(一)--linux系统常见命令及其文件互传(2)
2.使用 Linux 系统的常用命令 启动 Linux 虚拟机,进入 Linux 系统,通过查阅相关 Linux 书籍和网络资料,或者参考 本教程官网的“实验指南”的“Linux 系统常用命令”,完成 ...
- pycharm中Terminal中运行用例
1.设置终端路径 2.单个用例文件运行 3.多个用例文件,例如加载用例的文件运行 1.可能会出现如下错误(参考:https://blog.csdn.net/qq_36829091/article/d ...
- Mybatis笔记一
课程安排: mybatis和springmvc通过订单商品 案例驱动 第一天:基础知识(重点,内容量多) 对原生态jdbc程序(单独使用jdbc开发)问题总结 mybatis框架原理 (掌握) myb ...
- Struts2学习(六)
拦截器原理 1.如图所示,Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一 ...
- mybaits requestMap与requestType,以及对应的注解
有的时候不喜欢用xml配置文件,但是xml配置文件的开发使用简单,自己经常要用到: 因为代码维护的缘故,有的时候看别人的代码,可能存在大量的mappper文件,也不是你想用注解就用注解的: 下面我还是 ...
- js获取一个页面 是从哪个页面过来的
document.referrer 获取来源页面的url console.log(document.referrer) if(document.referrer=="http://127.0 ...
- 浏览器输入URL后HTTP请求返回的完整过程
图:
- 141、Java内部类之实例化外部类对象
01. 代码如下: package TIANPAN; class Outer { // 外部类 private static String msg = "Hello World !" ...
- 为什么maven没有.m2文件
该问题可能描述不清,建议你重新提问 为什么maven没有.m2文件 彼岸之恋°DD | 浏览 4793 次 问题未开放回答 2016-09-23 17:29 最佳答案 对于初学者在安装配置好maven ...