[数据结构]KMP小结
KMP小结
By Wine93 2013.9
1.学习链接: http://www.matrix67.com/blog/archives/115
2.个人小结
1.KMP在字符串中匹配中起着巨大作用,可以在O(n+m)内完成
2.要充分理解next 数组,其求法和next数组的含义(最长后缀等于最长前缀),了解其用途,下面我就next数组在求字符串最小周期中的应用举例
(1).什么是字符串最小周期?
Ex:字符串ababab,最小周期为2,为ab
Ex:字符串abcd,最小周期为4,为abcd
(2)最小周期的一个性质
如果len%(len-next[len])==0,则该字符串的最小周期为len-next[len]
(3)性质的证明
欲证:若len%(len-next[len])==0, 则该字符串的最小周期为len-next[len] (len表示该字符串长度)
证:我们分2部分证
① 若len%(len-next[len])==0,len-next[len]为字符串s的周期
② 证明len-next[len]就是其最小周期
因为next数组的含义是最长后缀等于最长前缀,所以s[ 1……next[len] ]
和s[next[len]+1……len ]是相等的,如上图,线段(1)和线段(2)相等
因为len%(len-next[len])==0,所以我们把线段(2)可以平均分成很多等份(图中假设为4份),每份长度都为s1,线段(1)也可以分成同等份,如上图,根据next数组的定义,s1=s2,又因为s2=s3,而s3=s4….所以依次类推可得s1=s2=s3=s4=s5=s6=s7=s8,所以,s1是字符串s的周期,所以①得证
若len-next[len]不是其最小周期,也就是说存在更小的长度是字符串s的周期,也就是说next[len]要变大(也就是说最长前缀等于最长后缀的值要增大),而根据next数组的定义,next[len]就是已经是最大值(已经是最长前缀等于最长后缀),所以相互矛盾,所以②得证
综上所述: 如果len%(len-next[len])==0,则该字符串的最小周期为len-next[len] (len表示该字符串长度)
3.相关题目:
(1)循环节相关:
POJ 2406 Period http://poj.org/problem?id=2406
# include<cstdio>
# include<cstring>
using namespace std; # define N
int next[N]; void getnext(char *s)
{
int i,j,len=strlen(s);
next[]=j=-;
for(i=;i<len;i++)
{
while(j>=&&s[j+]!=s[i])
j=next[j];
if(s[i]==s[j+])
j++;
next[i]=j;
}
} int main()
{
int i,len;
char s[N];
while(scanf("%s",s)!=EOF&&s[]!='.')
{
getnext(s);
len=strlen(s);
if(next[len-]!=-&&len%(len--next[len-])==)
printf("%d\n",len/(len--next[len-]));
else
printf("1\n");
}
return ;
}
POJ 2406
HDU 3746 Cyclic Nacklacehttp://acm.hdu.edu.cn/showproblem.php?pid=3746
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; # define N
int Next[N]; void getnext(char *s)
{
int i,j,len=strlen(s);
Next[]=j=-;
for(i=;i<len;i++)
{
while(j>=&&s[j+]!=s[i])
j=Next[j];
if(s[j+]==s[i])
j++;
Next[i]=j;
}
} int main()
{
int T,L,pos,m,d;
char s[N];
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
getnext(s);
L=strlen(s);
if(Next[L-]==-) printf("%d\n",L);
else
{
m=L--Next[L-];
d=Next[L-]+; // (d+x)==0(mod m)
printf("%d\n",(m-d%m)%m);
}
}
return ;
}
HDU 3746
CF 182D Common Divisors http://codeforces.com/problemset/problem/182/D
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; # define N
int Next[N]; void getnext(char *s)
{
int i,j,len=strlen(s);
Next[]=j=-;
for(i=;i<len;i++)
{
while(j>=&&s[j+]!=s[i])
j=Next[j];
if(s[j+]==s[i])
j++;
Next[i]=j;
}
} int main()
{
int i,len,L1,L2,ans;
char s1[N],s2[N];
while(scanf("%s%s",s1,s2)!=EOF)
{
ans=;
L1=strlen(s1),L2=strlen(s2);
strcat(s1,s2);
getnext(s1);
len=L1+L2;
if(Next[len-]==-||len%(len--Next[len-]))
printf("0\n");
else
{
int m=len--Next[len-];
if(L1%m||L2%m)
printf("0\n");
else
{
for(i=m;i<=L1&&i<=L2;i+=m)
if(L1%i==&&L2%i==)
ans++;
printf("%d\n",ans);
}
}
}
return ;
}
CF 182D
(2)Next数组:
HDU 3336 Count the string http://acm.hdu.edu.cn/showproblem.php?pid=3336
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; # define MOD
# define N
int Next[N];
int num[N]; void getnext(char *s)
{
int i,j,len=strlen(s);
Next[]=j=-;
for(i=;i<len;i++)
{
while(j>=&&s[j+]!=s[i])
j=Next[j];
if(s[j+]==s[i])
j++;
Next[i]=j;
}
} int main()
{
int T,len,i,ans;
char s[N];
scanf("%d",&T);
while(T--)
{
ans=;
memset(num,,sizeof(num));
scanf("%d%s",&len,s);
getnext(s);
for(i=len-;i>=;i--)
{
num[i]++;
if(num[i]>=MOD)
num[i]-=num[i]/MOD*MOD;
if(Next[i]!=-)
{
num[Next[i]]+=num[i];
if(num[Next[i]]>=MOD)
num[Next[i]]%=MOD;
}
ans=(ans+num[i])%MOD;
}
printf("%d\n",ans);
}
return ;
}
HDU 3336
HDU 2594 Simpsons’ Hidden Talents http://acm.hdu.edu.cn/showproblem.php?pid=2594
# include<cstdio>
# include<cstring>
using namespace std; # define N
char s1[N],s2[N];
int Next[N]; void getnext(char *s)
{
int i,j,len=strlen(s);
Next[]=j=-;
for(i=;i<len;i++)
{
while(j>=&&s[j+]!=s[i])
j=Next[j];
if(s[j+]==s[i])
j++;
Next[i]=j;
}
} int main()
{
int i,L1,L2,pos,ans;
while(scanf("%s%s",s1,s2)!=EOF)
{
L1=strlen(s1),L2=strlen(s2);
strcat(s1,s2);
getnext(s1);
pos=L1+L2-;
/* for(i=0;i<=pos;i++)
printf("%d ",Next[i]);*/
ans=-;
while(pos!=-)
{
if(Next[pos]!=-&&Next[pos]<L1&&L2-(Next[pos]+)>=)
{
ans=Next[pos];
break;
}
pos=Next[pos];
}
if(ans==-) printf("0\n");
else
{
for(i=;i<=ans;i++) printf("%c",s1[i]);
printf(" %d\n",ans+);
}
}
return ;
}
HDU 2594
(3)KMP匹配:
HDU 1711 Number Sequence http://acm.hdu.edu.cn/showproblem.php?pid=1711
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; # define N
int a[N],b[N];
int Next[N]; void getnext(int x[],int n)
{
int i,j;
Next[]=j=-;
for(i=;i<n;i++)
{
while(j>=&&x[j+]!=x[i])
j++;
if(x[j+]==x[i])
j++;
Next[i]=j;
}
} int kmp(int a[],int n,int b[],int m)
{
int i,j=-;
getnext(b,m);
for(i=;i<n;i++)
{
while(j>=&&b[j+]!=a[i])
j=Next[j];
if(a[i]==b[j+])
j++;
if(j+==m)
return i-m+;
}
return -;
} int main()
{
int T,n,m,i;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i=;i<n;i++)
scanf("%d",&a[i]);
for(i=;i<m;i++)
scanf("%d",&b[i]);
int ans=kmp(a,n,b,m);
printf("%d\n",ans);
}
return ;
}
HDU 1711
CF 8A Train and Peter (string::find也可以) http://codeforces.com/problemset/problem/8/A
4.KMP模板
# include<cstdio>
# include<cstring>
# include<vector>
# include<algorithm>
using namespace std; # define VI vector<int> //返回所有匹配点
# define N
int Next[N]; void getnext(char *s)
{
int i,j,len=strlen(s);
Next[]=j=-;
for(i=;i<len;i++)
{
while(j>=&&s[j+]!=s[i]) j=Next[j];
if(s[j+]==s[i]) j++;
Next[i]=j;
}
} VI kmp(char *s,char *ch)
{
int i,j,len=strlen(s),m=strlen(ch);
VI ans;
ans.clear();
getnext(ch);
j=-;
for(i=;i<len;i++)
{
while(j>=&&ch[j+]!=s[i]) j=Next[j];
if(ch[j+]==s[i]) j++;
if(j+==m) ans.push_back(i-m+);
}
return ans;
}
KMP模板
5.总结:
KMP的应用很大,一定要深入理解,尤其是next数组, 这对处理字符串匹配问题有着重大影响,AC自动机就是基于KMP来实现的.同时也要理解next数组的局限性(只能是后缀与前缀的对应关系),这对解题时的判断有着重要作用
注:后缀数组可以解决KMP的一部分局限性
[数据结构]KMP小结的更多相关文章
- 数据结构--KMP算法总结
数据结构—KMP KMP算法用于解决两个字符串匹配的问题,但更多的时候用到的是next数组的含义,用到next数组的时候,大多是题目跟前后缀有关的 . 首先介绍KMP算法:(假定next数组已经学会, ...
- KMP Algorithm 字符串匹配算法KMP小结
这篇小结主要是参考这篇帖子从头到尾彻底理解KMP,不得不佩服原作者,写的真是太详尽了,让博主产生了一种读学术论文的错觉.后来发现原作者是写书的,不由得更加敬佩了.博主不才,尝试着简化一些原帖子的内容, ...
- 数据结构———KMP
今天照着课本敲了一下KMP.. 以OJ上的一个题为例敲了一下.. 题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem& ...
- 【暑假】[实用数据结构]KMP
KMP算法 KMP算法是字符串匹配算法,可以在O(n)的时间完成,算法包含两部分,分别是:构造适配函数与两串匹配. 失配边的使用大大提高了算法效率,可以理解为已经成功匹配的字符不在重新匹配,因为我们已 ...
- OpenJudge_cdqz 数据结构版块小结
题目整理 Challenge 0 随机线性存储表-easy Challenge 1 链表数组-easy Challenge 2 可持久化Treap的可持久化运用-hard Challenge 3 ...
- 实验数据结构——KMP算法Test.ming
翻译计划 小明初学者C++,它确定了四个算术.关系运算符.逻辑运算.颂值操作.输入输出.使用简单的选择和循环结构.但他的英语不是很好,记住太多的保留字,他利用汉语拼音的保留字,小屋C++,发明 ...
- 大话数据结构——KMP算法(还存在问题)
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html /*#include& ...
- KMP小结
1. KMP模版: 代表题目:POJ 3641 Oulipo KMP http://blog.csdn.net/murmured/article/details/12871891 char P[MAX ...
- 数据结构——KMP算法
算法介绍 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法).KMP算法的核心是利用 ...
随机推荐
- 伪静态<-> 动态页,伪静态,真静态的比较和选择
动态页,伪静态,真静态优缺点的比较 动态页不利于SEO优化. 动态页常常因为传参数的缘故后面会带一连串的问号.而搜索引擎会因为里面问号导致死循(机器人陷阱Spidertraps),所以带问号的地址搜索 ...
- [转]Arrays.sort()你应该知道的事
以下内容转自: 原文链接: programcreek 翻译: ImportNew.com- 刘志军 译文链接: http://www.importnew.com/8952.html --------- ...
- tomcat项目发布 更改小猫图标 及自定义错误404界面
tomcat发布项目的时候遇到些小问题 不过解决了 问题1. 整个服务器的404自定义界面问题 解决方法: 在tomcat安装目录下conf中web.xml中修改配置文件 <error-page ...
- linux系统设置静态IP 查看网卡配置文件
http://jingyan.baidu.com/article/455a99508be7cda167277865.html vi /etc/sysconfig/network-scripts/ifc ...
- linux 下echo命令写入文件内容
http://blog.csdn.net/xukai871105/article/details/35834703 echo "Raspberry" > test.txt
- Time, Clocks, and the Ordering of Events in a Distributed System
作者:Leslie Lamport(非常厉害的老头了) 在使用消息进行通信的分布式系统中,使用物理时钟对不同process进行时间同步与事件排序是非常困难的.一是因为不同process的时钟有差异,另 ...
- HDU 4050 wolf5x 概率dp 难度:1
http://acm.hdu.edu.cn/showproblem.php?pid=4050 题意: 现在主角站在0处,需要到达大于n的位置 主角要进入的格子有三种状态: 0. 不能进入 1. 能进入 ...
- hdu 4606 Occupy Cities
http://acm.hdu.edu.cn/showproblem.php?pid=4606 两点之间如果有线段相隔的话,他们的最短路就需要经过线段的端点 把所有线段的端点也加入点数组中,求任意两个点 ...
- UVa 11426 - GCD - Extreme (II)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- Oracle连接出现TNS:no listener或者ORA-12514: TNS:listener does not currently know
1.Message 850 not found; No message file for product=network, facility=NL 提示框:TNS:no listener 解决办法: ...