KMP回顾学习
记住这张图,getnext就是对一个已知的待匹配的串进行分析,nex【i】表示当a【i】匹配失败后我能跳到哪里,继续尝试匹配,而不是每一次失败都从头再来,先来看看代码
const int maxn = 1e5;
int net[maxn];
char a[maxn];
void get_next(int len)
{
int i = 0,j = -1;
nex[0] = -1;//别忘记初始化,和汽车的发动机一样重要
while(i < len)
{
if(j == -1 || a[i] == a[j])
{
net[++i] = ++j;
}
else
{
j = net[j];
}
}
}
j = -1是一个特殊判断代表到了头是在不能尝试匹配了得从头开始了
而a[i] = a[j]的时候,就可已更新i + 1位的net数组,他能跳的位置也就是j + 1
当a[i] != a[j]的时候,我们也是寻找的它能跳的最大(远)的点,所以先跳到net[j]去尝试匹配,……直到j=-1不能配为止,那么net[i+1]=0,也只能从头开始了
———————————————————————————————————————————————
看HDU3336
让你求每一个前缀的出现次数,是对next数组意义的考察
看那个图:是在j位置失配时能跳到的最远的位置,前提是p0 --pk-1和pj-k--pj-1相同(匹配)才能跳到k-1+1的位置再次进行匹配,也就是每一个>0的next【i】都代表0——i-1的字符串内有匹配项,我们要考虑的是断开的位置,是next数组断开的位置,如果next[i] + 1 == next[i+1]的化,代表匹配项还没结束,还在一直匹配着,我们得到结束点,然后计算前缀重复出现的次数
注意这个题是不允许交叉计算的例如ababa中aba止出现了一次,所以对我们找到的部分最长匹配串,我们是不用考虑其内部还有子匹配串的情况的 ,因为会交叉
例如a b a b a b
-1 0 0 1 2 3 4
面对一整个串我们只能找到的是abab这个部分最长匹配串对应的next值是4,最后结果加的4对应的分别是a,ab,(ab)a,(ab)ab,这是存在交叉
时候的运算
不存在交叉的时候最好考虑了……
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int maxn = 200005; int net[maxn];
char a[maxn]; void get_next(int len) //KMP原始next值
{
int i = 0, j = -1;
net[0] = -1;
while (i < len)
{
if (j == -1 || a[i] == a[j])
{
net[++i] = ++j;
}
else j = net[j];
}
}
int main()
{
int t, res,len;
scanf("%d", &t);
while(t--)
{
scanf("%d",&len); scanf("%s",&a);
get_next(len);
res = net[len] + len;
for (int i = 0; i < len ; i++)
if (net[i] > 0 && net[i] + 1 != net[i+1])
res += net[i];
printf ("%d\n", res%10007);
}
return 0;
}
这个题不大好~~就这样草草结束吧
——————————————————————————————————————————————————
再来看一道2087这是在kmp这个题比较入门,正常的匹配过程中改变一下条件就好了4
int kmp(int len1,int len2)
{
int i = 0,j = 0,cnt = 0;
while(i < len1)
{
if(j == -1 || a[i] == b[j])
{
i++;
j++;
}
else
{
j = net[j];
}
if(j == len2)
{
j = 0;
cnt++;
}
}
return cnt;
}
然后HDU1867
考的是字符串相加,一个串的前缀和另一个串的后缀可以结合,优先输出结合后长度最小的,如果长度都相等,救输出字典序最小的
一开始我做的相当的麻烦,没有一点模块化编程的想法
实现模块化就是用一个函数实现a + b 和b + a 的结果
在这里用到了指针!!
在kmp中我们求net(因为net不像是原来的题目一样求一次就过了,他需要求b再求a)
然后是改编版的kmp:因为我们寻求的是前缀和后缀相同,所以为了避免完全包含的情况入abcbc 和 bc的出现我们while的条件是i<l1:也就是母串必须遍历到头,且注意对j 重新更新为0的判断(当j == l2 && i != l1)的时候才进行
然后返回j的位置,就是,匹配后我该输出的另一个的骑士位置
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define INF 0x3f3f3f3f
#define maxn 100000+10
using namespace std; char str1[maxn], str2[maxn];
int net[maxn]; void getnet(char *x,int len)
{
int i = 0,j = -1;
net[0] = -1;
while(i < len)
{
if(j == -1 || x[i] == x[j])
{
net[++i] = ++j;
}
else j =net[j];
}
}
int kmp(char *s1,char *s2)
{
int i = 0,j = 0;
int l1 = strlen(s1),l2 = strlen(s2);
getnet(s2,l2);
while( i < l1)
{
if(j == -1 || s1[i] == s2[j])i++,j++;
else j =net[j];
if(j == l2 && i != l1)() j = 0;
}
return j;
}
int main()
{
while(~scanf("%s",str1))
{
scanf("%s",str2);
int tem1 = kmp(str1,str2);
int tem2 = kmp(str2,str1);
if(tem1 > tem2)
{
printf("%s",str1);
printf("%s\n",&str2[tem1]);
}
else if(tem1 < tem2)
{
printf("%s",str2);
printf("%s\n",&str1[tem2]);
}
else
{
if(strcmp(str1,str2) < 0)printf("%s%s\n",str1,&str2[tem1]);
else printf("%s%s\n",str2,&str1[tem2]);
}
}
return 0 ;
}
KMP回顾学习的更多相关文章
- 字符串匹配算法——KMP算法学习
KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...
- [KMP]【学习笔记】
Oulipo Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 36916 Accepted: 14904 Descript ...
- KMP算法学习
kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置.常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(n ...
- Asp.net Form登陆认证的回顾学习
asp.net网站中,我最常用的就是Form认证了,在实现登陆时,利用Form认证实现用户的访问权限,哪些页面是可以匿名登陆,哪些页面需要认证后才能访问,哪些页面不能访问等等权限.我还可在登陆时,使用 ...
- KMP 算法 学习 整理
我自己整理的KMP算法的PDF文件:http://pan.baidu.com/s/1o8yKIi2提取密码:8291 别的就不多说啥了,感谢来自海子 博客园的 资料--
- KMP算法 学习例题 POJ 3461Oulipo
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37971 Accepted: 15286 Description The ...
- KMP算法学习(详解)
kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚.在此,综合网上比较好 ...
- HDU 4333 Revolving Digits [扩展KMP]【学习笔记】
题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如 ...
- 省赛在即!最大流问题回顾学习!!DInic
Dinic是很好的算法,但是我还是从ek算法复习起步 面对最大流问题,印象最深的就是反向边的思想,他给我们提供了反悔的机会,其实现在放到实际上来想,可以相当于两边的水都流了这条边,只是方向不一样,放到 ...
随机推荐
- Dotfuscator Professional Edition获取代码发布和混淆代码
1 Dotfuscator Professional Edition 4.9 破解版 下载地址:http://www.pc0359.cn/downinfo/39815.html 备份地址:C:\D\9 ...
- 框架中spring有专门的类用于处理乱码
在三大框架spring中有专门的一个过滤器类用于处理乱码问题--->CharacterEncodingFilter 我们只需在web.xml中添加如下几行代码就可解决乱码问题 <filte ...
- Pandas数据规整
Pandas数据规整 数据分析和建模方面的大量编程工作都是用在数据准备上的,有时候存放在文件或数据库中的数据并不能满足数据处理应用的要求 Pandas提供了一组高级的.灵活的.高效的核心函数和算法,它 ...
- 杨辉三角(生成器generator)
生成器:(Python中,这种一边循环一边计算的机制,称为生成器:generator) 创建generator的方法: 1.把列表生成式的[]变为(),就创建了一个generator 例: 可以通过n ...
- 求含有n个因子的最小正整数(n<=1000000)
题目链接:https://ac.nowcoder.com/acm/contest/331/G 思路: 根据唯一分解定理,如果一个数n可以表示成 n=p1a1*p2a2*...*pkak (pi是第i个 ...
- zoj1003-Max Sum (最大连续子序列之和)
http://acm.hdu.edu.cn/showproblem.php?pid=1003 Max Sum Time Limit: 2000/1000 MS (Java/Others) Mem ...
- day2:vcp考试
Q21. An administrator has been instructed to secure existing virtual machines in vCenter Server.Whic ...
- ROS学习笔记二(创建ROS软件包)
catkin软件包的组成 一个软件包必须满足如下条件才能被称之为catkin软件包: 必须包含一个catkin编译文件package.xml(manifests文件),此文件包含了描述该软件包的重要信 ...
- Spring框架整合Struts2框架的传统方法
1. 导入CRM项目的UI页面,找到添加客户的页面,修改form表单,访问Action * 将menu.jsp中133行的新增客户的跳转地址改为:href="${pageContext.re ...
- java 错误: 找不到或无法加载主类
这个问题应该很常见的,笔者经常手工编译一些测试代码或者小工具,经常用到 javac和java来编译并运行一些简单的小工具. 以Hello World来测试. HelloWorld.java publi ...