记住这张图,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回顾学习的更多相关文章

  1. 字符串匹配算法——KMP算法学习

    KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...

  2. [KMP]【学习笔记】

    Oulipo Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 36916   Accepted: 14904 Descript ...

  3. KMP算法学习

    kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置.常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(n ...

  4. Asp.net Form登陆认证的回顾学习

    asp.net网站中,我最常用的就是Form认证了,在实现登陆时,利用Form认证实现用户的访问权限,哪些页面是可以匿名登陆,哪些页面需要认证后才能访问,哪些页面不能访问等等权限.我还可在登陆时,使用 ...

  5. KMP 算法 学习 整理

    我自己整理的KMP算法的PDF文件:http://pan.baidu.com/s/1o8yKIi2提取密码:8291 别的就不多说啥了,感谢来自海子 博客园的 资料--

  6. KMP算法 学习例题 POJ 3461Oulipo

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37971   Accepted: 15286 Description The ...

  7. KMP算法学习(详解)

    kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚.在此,综合网上比较好 ...

  8. HDU 4333 Revolving Digits [扩展KMP]【学习笔记】

    题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如 ...

  9. 省赛在即!最大流问题回顾学习!!DInic

    Dinic是很好的算法,但是我还是从ek算法复习起步 面对最大流问题,印象最深的就是反向边的思想,他给我们提供了反悔的机会,其实现在放到实际上来想,可以相当于两边的水都流了这条边,只是方向不一样,放到 ...

随机推荐

  1. scala 建模

    // train multinomial logistic regression val lr = new LogisticRegressionWithLBFGS() .setIntercept(tr ...

  2. sql server profiler 的使用

    sql server profiler  是作为监听sql语句执行的软件, 主要是看NTUserName,system是系统的,看自己数据库的名字.

  3. 项目中调试SQLServer 方便的查看SQL语句的执行时间的方法

    第一种方法,先记录执行前的时间,然后在记录执行Sql后的时间,然后做减法 1 第一种方法: 2 declare @begin_date datetime 3 declare @end_date dat ...

  4. JdbcTemplate实现CRUD操作

    ------------------siwuxie095                                     JdbcTemplate 实现 CRUD 操作         1.J ...

  5. 数据流中位数 · data stream median

    [抄题]: 数字是不断进入数组的,在每次添加一个新的数进入数组的同时返回当前新数组的中位数. [思维问题]: [一句话思路]: 左边x个元素,右边要有x+1个元素,因此利用maxheap把左边的最大值 ...

  6. swift 移除所有子控件

    /// 移除所有子控件 func removeAllSubViews(){ if self.view.subviews.count>0{ self.view.subviews.forEach({ ...

  7. VMware安装centos虚拟机 通过NAT与主机互通并能上网

    1.关于centos虚拟机的安装,我这里就不详细说明了,网上有很多教程,默认你们已经安装好.       (我的环境是centos6.6 x86 最小安装版) 2.右键虚拟主机,选择设置选项. 3.在 ...

  8. UI小白如何快速提升自己

    作为一名经历过UI学习的过来人,这些观点是自己在整个学习的过程中总结的. 希望可以对大家有所帮助,可以让刚开始接触UI的人少走弯路吧,话不多说. 快速进入主题. ​ 那么UI小白到底如何快速提成自己呢 ...

  9. An integration of deep learning and neuroscience

    Recently, I have read a paper about the integration of deep learing and neuroscience, which elaborat ...

  10. 使用WebUploader客户端批量上传图片,后台使用springMVC接收实例

    使用WebUploader客户端批量上传图片,后台使用springMVC接收实例 我是搞Java后台的,因为最近主管让用webUploader写客户端,但是在网上找了很多,能够复制就能用的并没有几个, ...