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是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣.他们约定好互相帮助 ...
随机推荐
- 第四节:Vuejs组件及组件之间的交互
一. 组件及其交互 1.组件的注册 (1).全局注册 Vue.component('组件名称', { }) 第1个参数是标签名称,第2个参数是一个选项对象. 选项参数包括 data:必须是一个func ...
- 安装mysql常见错误解决方法
Mysql ERROR 1698 (28000) 解决 解决mysqld_safe Directory '/var/run/mysqld' for UNIX socket file don't exi ...
- maven设置jdk版本
方法一:在maven文件夹下的settings.xml中添加 <profile> <id>jdk-1.8</id> <activation> <a ...
- vim功能之替换和查找
vim有着强大的替换和查找功能,若能进行熟练的运用,可以让工作效率得到一个很大程度的提高. 替换 语法:[addr]s/源字符串/目的字符串/[option] [addr]表示检索范围,如: &quo ...
- java_3:JVM、JRE、JDK区别和联系
首先 三者之间存在包含关系JVM + 核心类库 = JREJRE + java开发工具(javac.exe/jar.exe) = JDK 什么是JVM? 我们知道Java语言有一个独特的优点就是可以跨 ...
- Java源码-集合-ArrayList
基于JDK1.8.0_191 介绍 在Java中,对于数据的保存和使用有多种方式,主要的目的是以更少的资源消耗解决更多的问题,数组就是其中的一种,它的特点是所有的数据都保存在内存的一段连续空间中, ...
- windows下svn post-commit的实现
前言: 好的!在结束了上一博客教程的Subversion安装之后.我们开始了下一项工作,windows版本下 svn post-commit的实现.说实话,这方面的知识网上的知识并不是很多~~~~~~ ...
- A way to use NAT network by using Oracle virtualBox
That is true. Vmware is easy and confortable tools to make vitrual machines than Oracle virtual box ...
- 使用 JvisualVM 监控 spark executor
使用 JvisualVM,需要先配置 java 的启动参数 jmx 正常情况下,如下配置 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmx ...
- linux----Nginx能做什么
linux----Nginx能做什么 标签: nginx负载均衡代理服务器 2017-04-01 14:15 588人阅读 评论(0) 收藏 举报 .embody{ padding:10px 10px ...