之前在codeforces上做了一道类似KMP的题目,但由于之前没有好好掌握,现在又基本忘记,并没能解答。下面是对KMP算法的一点小总结。

  首先KMP算法的核心是纸在匹配过程中,利用模式串的前后缀来加速匹配过程,这一点在自己实验时就可以发现了。其次时KMP算法的核心Next数组,next[j]=k表示对于模式串的【0...j-1】位,最长存在长度为k的相同前后缀,值得注意的是对于kmp而言是不能出现next[j]=j的情况的。而next数组的计算方法我认为本质上还是DP,但是在状态转移过程中又用到了递归的想法,因此使得算法变得复杂。

  下面是codeforces上的next数组变种题:http://codeforces.com/contest/1200/problem/E

  需要利用next数组的思想,将要合并的两个字符串构建成“S2+S1"的形式,其中的“+”可以防止匹配越界,还应该注意构建时取S1.S2的最小长度从而减小时间复杂度。最后利用next[]的最后一位即可得到合并部分的长度。

  这里是自己比较习惯的利用for循环完成next数组构建的写法。

 #include <stdio.h>

char ch[];
int next[]; char* mmerge(char* ch1,char* ch2,int &len1,int len2)
{
//printf("%d %d ",len1,len2);
int len=len1;if (len2<len) len=len2; for (int i=;i<len;i++)
ch[i]=ch2[i];
ch[len]='+';
for (int i=len*,j=len1-;i>len;i--,j--)
ch[i]=ch1[j];
ch[len*+]=;
// printf("%s\n",ch); next[]=;
for (int i=;i<=len*;i++)
{
int j=next[i-];
while (j && ch[i]!=ch[j])
j=next[j-];
if ( ch[i]==ch[j] ) next[i]=j+;
else next[i]=;
} //printf(" %d ",next[len*2]);
for(int i=next[len*];ch2[i];i++,len1++ )
ch1[len1]=ch2[i];
ch1[len1]=; //printf("%s\n\n",ch1);
return ch1;
} int main()
{
char ch1[];
int n;scanf("%d",&n);
scanf("%s",ch1);
int len1=;
while (ch1[len1]) len1++;
for(int i=;i<n;i++)
{
char ch2[];
scanf("%s",ch2);
int len2=;while (ch2[len2]) len2++;
mmerge(ch1,ch2,len1,len2);
}
printf("%s",ch1);
}

  也有正常使用while循环的写法(可能不标准吧)

#include <stdio.h>

char ch[];
int next[]; char* mmerge(char* ch1,char* ch2,int &len1,int len2)
{ int len=len1;if (len2<len) len=len2; for (int i=;i<len;i++)
ch[i]=ch2[i];
ch[len]='+';
for (int i=len*,j=len1-;i>len;i--,j--)
ch[i]=ch1[j];
ch[len*+]=; next[]=;
int now=,mlen=;
while (now<=len*)
{
if (ch[now]==ch[mlen])
{
next[now]=mlen+;
now++;mlen++;
}
else
if (mlen==)
next[now++]=;
else
mlen = next[mlen-];
} for(int i=next[len*];ch2[i];i++,len1++ )
ch1[len1]=ch2[i];
ch1[len1]=; return ch1;
} int main()
{
char ch1[];
int n;scanf("%d",&n);
scanf("%s",ch1);
int len1=;
while (ch1[len1]) len1++;
for(int i=;i<n;i++)
{
char ch2[];
scanf("%s",ch2);
int len2=;while (ch2[len2]) len2++;
mmerge(ch1,ch2,len1,len2);
}
printf("%s",ch1);
}

  在程序中,也大胆尝试了以前不敢用的传递对象指针以及利用引用&完成传值的操作,希望以后能多用一些这种编程方式,有利于工程实践。另外最开始将ch数组与next数组放置于mmerge函数中,似乎出现了栈溢出的问题(以后需要关注,还不太明白)。

  接着做了一道正常KMP例题,http://acm.hdu.edu.cn/showproblem.php?pid=1686,问S1在S2串中出现了多少次?

#include <stdio.h>

int ans( char* S, char* P, int* next )
{
int aans=;
int len1=;while (S[len1]) len1++;
int len2=;while (P[len2]) len2++;
next[]=-;
int now=,mlen=-;
while (now<len1)
{
if (mlen==- || S[now]==S[mlen] )
{
mlen++;
now++;
next[now]=mlen;
}
else
mlen=next[mlen];
} int i=,j=;
while (j<len2)
{
if (i==len1) aans++,i=next[i];
if (i==- || S[i]==P[j])
i++,j++;
else
i=next[i]; }
if (i==len1) aans++;
return aans; } int main()
{
int T;scanf("%d",&T);
while (T--)
{
char ch1[];
char ch2[];
scanf("%s%s",ch1,ch2);
int next[];
printf("%d\n", ans(ch1,ch2,next) );
}
}

  对于KMP,目前理解了原理,自己也能写出代码,不过感觉还是不够熟练,时常回来看看吧:)

kmp算法学习 与 传参试验(常回来看看)的更多相关文章

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

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

  2. KMP算法学习

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

  3. KMP 算法 学习 整理

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

  4. KMP算法学习(详解)

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

  5. 字符串匹配的BF算法和KMP算法学习

    引言:关于字符串 字符串(string):是由0或多个字符组成的有限序列.一般写作`s = "123456..."`.s这里是主串,其中的一部分就是子串. 其实,对于字符串大小关系 ...

  6. KMP 算法学习

    KMP算法是用来做字符串匹配的.关于字符串匹配,最简单最容易想到的方法是暴利查找,使用双重for循环处理. 该方法的时间复杂度为O((n-m+1)*m) (n为目标串T长度,m为模式串P长度, 从T中 ...

  7. KMP算法学习以及小结(好马不吃回头草系列)

    首先请允许我对KMP算法的三位创始人Knuth,Morris,Pratt致敬,这三位优秀的算法科学家发明的这种匹配模式可以大大避免重复遍历的情况,从而使得字符串的匹配的速度更快,效率更高. 首先引入对 ...

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

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

  9. Django学习----js传参给view.py

    需求: 散点图中每选择一个点,获取到id之后传给view.py,根据这个id进行sql语句的查询. 问题: 要求实时查询 解决办法: ajax查询 js页面 .on("mousedown&q ...

随机推荐

  1. 在docker中开启新的container

    当你在启动某个容器类型的时候  如果产生了类似的错误: docker: Error: No such image: b27f5dfcfc70c16d7b135889460def6b3f831bcc72 ...

  2. 定时器任务django-crontab的使用【静态化高频率页面,增加用户体验】【系统的定时器,独立于项目执行】【刘新宇】

    页面静态化 思考: 网页的首页访问频繁,而且查询数据量大,其中还有大量的循环处理. 问题: 用户访问首页会耗费服务器大量的资源,并且响应数据的效率会大大降低. 解决: 页面静态化 1. 页面静态化介绍 ...

  3. mybatis学习笔记(二)

    三种查询方式,由<resultType 属性控制> 第一种 selectList() 返回值为LIst List<People> selectList = session.se ...

  4. Go中的并发编程和goroutine

    并发编程对于任何语言来说都不是一件简单的事情.Go在设计之初主打高并发,为使用者提供了goroutine,使用的方式虽然简单,但是用好却不是那么容易,我们一起来学习Go中的并发编程. 1. 并行和并发 ...

  5. abc -- 牛客

    题目描述 设a.b.c均是0到9之间的数字,abc.bcc是两个三位数,且有:abc+bcc=532.求满足条件的所有a.b.c的值. 输入描述: 题目没有任何输入. 输出描述: 请输出所有满足题目条 ...

  6. React Native-安卓环境的搭建

    最近公司做一个项目,项目中使用React Native(简称RN)来写安卓APP,现在我分享下安卓环境搭建的过程. 我参照https://reactnative.cn/docs/getting-sta ...

  7. Python.append()与Python.extend()的区别

    lst=[1,2] >>>[1,2] lst.append([3,4]) >>>[1, 2, [3, 4]] lst.extend([3,4]) >>& ...

  8. Ubuntu 17 安装Chrome浏览器

    1.进入下载文件存放目录 cd Downloads 2.下载chrome文件 2.1 32位使用如下命令 wget https://dl.google.com/linux/direct/google- ...

  9. mssql server master 数据库还原

    今天想试一下master数据库还原,在进入单用户模式的时候,在命令行输入sqlserver.exe -c -f -m结果显示 'sqlserver.exe' 不是内部或外部命令,也不是可运行的程序或批 ...

  10. luoguP2444_[POI2000]病毒

    题意 给定多个01模式串,问是否存在一个无限长的字符串不包含任何一个模式串. 分析 好像数据有点水,网上一大堆题解连样例都没过??? 多模式串,先把AC自动机建出来再说. 反向考虑,若存在一个无限长的 ...