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算法复习起步 面对最大流问题,印象最深的就是反向边的思想,他给我们提供了反悔的机会,其实现在放到实际上来想,可以相当于两边的水都流了这条边,只是方向不一样,放到 ...
随机推荐
- C#实现二维码生成与解码
前几天公司内部分享了一个关于二维码的例子,觉得挺好玩的,但没有提供完整的源码.有时候看到一个好玩的东西,总想自己Demo一个,于是抽空就自己研究了一下. 一.二维码的原理 工欲善其事,必先利其器.要生 ...
- java多线程实例
import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurr ...
- MyBatis 通用Mapper接口 Example的实例
一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 int countByExample(UserExample example) thorws SQLException ...
- PR数量回写重复
- flush(), clear(), save()的简单解释
hibernate最新发布包的javadoc里对这三个方法的解释是: clear() :Completely clear the session.清空session,该清空操作只对于要保存的.删除的和 ...
- for of 与 for in 的区别
遍历数组通常使用for循环,ES5的话也可以使用forEach,ES5具有遍历数组功能的还有map.filter.some.every.reduce.reduceRight等,只不过他们的返回结果不一 ...
- zoj1003-Max Sum (最大连续子序列之和)
http://acm.hdu.edu.cn/showproblem.php?pid=1003 Max Sum Time Limit: 2000/1000 MS (Java/Others) Mem ...
- 1.Two Sum (Array; HashTable)
Given an array of integers, find two numbers such that they add up to a specific target number. The ...
- phpStudy4——前端页面使用Ajax请求并解析php返回的json数据
项目需求: 在html页面显示所有用户列表信息. 需求分析: 1. html页面使用ajax向后端php请求用户数据 2. php脚本查询数据库,并将查询后的结果以json格式返回前端html页面 3 ...
- 2-Qt关闭子窗口时执行特定代码
https://blog.csdn.net/naibozhuan3744/article/details/82689434 本文主要总结在关闭qt的QWidget子窗口瞬间,执行特定代码.由于主窗口关 ...