之前在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. 在 dotnet core (C#)下的颜色渐变

    直接使用等比例抽样算法,连同透明度一起计算. public IList<Color> ShadeColors(Color c1, Color c2, int resultCount) { ...

  2. web渗透---第二天

    协议常识 HTTP协议 百度百科的解释:超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议. 所有的WWW文件都必须遵守这个标准. ...

  3. cogs 1317. 数列操作C 区间修改 区间查询

    1317. 数列操作C ★★★   输入文件:shuliec.in   输出文件:shuliec.out   简单对比时间限制:1 s   内存限制:128 MB [题目描述] 假设有一个长度为 n( ...

  4. 洛谷P1510 题解

    前言: 其实这道题挺水的,但我居然把ta想成了 贪心 啪啪打脸 好了,废话不多说. 思路: step 1:先翻译以下题意,其实就是求出最多消耗多少体力能把东海填满,如果不能填满,就输出"Im ...

  5. Web很脆弱,SQL注入要了解

    SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 通过一下的例子更形象的了解SQL注入: 有一个Login ...

  6. 《白帽子讲web安全》——吴瀚清 阅读笔记

    浏览器安全 同源策略:浏览器的同源策略限制了不同来源的“document”或脚本,对当前的“document”读取或设置某些属性.是浏览器安全的基础,即限制不同域的网址脚本交互     <scr ...

  7. NLP系列文章:子词嵌入(fastText)的理解!(附代码)

    1. 什么是fastText 英语单词通常有其内部结构和形成⽅式.例如,我们可以从"dog""dogs"和"dogcatcher"的字⾯上推 ...

  8. Mybatis框架(9)---Mybatis自定义插件生成雪花ID做为表主键项目

    Mybatis自定义插件生成雪花ID做为主键项目 先附上项目项目GitHub地址 spring-boot-mybatis-interceptor 有关Mybatis雪花ID主键插件前面写了两篇博客作为 ...

  9. 使用docker快速搭建本地环境

    在平时的开发中工作中,环境的搭建其实一直都是一个很麻烦的事情 特别是现在,系统越来越复杂,所需要连接的一些中间件也越来越多. 然而要顺利的安装好这些中间件也是一个比较费时费力的工作. 俗话说" ...

  10. SSH开发模式——Struts2(第一小节)

    在制定了学习计划的学习过程中,我感觉学习还是很有效率的.很短的时间内,我便学习完了JavaWeb的连接池.DbUtils框架及其一些工具类的使用. 学无止境,学习这些知识还远远不够,所以,在接下来的时 ...