拓展kmp算法可解决以下问题,给定两个字符串s1和s2,可以求出s1的extend数组(简记为ex),其中extend[i]表示s1从第i位开始的子串和s2的最大公共前缀长度,举个例子:可以看到extend[0]=4最长公共前缀是aaaa (s1=“aaaaaaa”,s2=“aaaa”)

一:暴力计算ex数组。
我们枚举s1的每一个位置,每次都从s2的开头开始匹配,直到失配为止。比如上图求解ex[0]时从0开始直到到达s2的最大长度失配,所以长度为s1;
但是暴力就有很多重复的比较,也就是已知的信息没有利用起来,如何利用起来呢?:当我们知道ex[0]=4的时候,我们就可以得到s1[0…3]=s2[0…3],即s1[1…3]=s2[1…3],我们引入一个针对于s2的next数组,next[i]=k表示 s2[0…k-1]=s2[i…i+k-1],如下图,我们看到next[1]=3,则说明s2[0…2]=s2[1…3],s2[1…3]=s1[1…3],得到s1[1…3]=s2[0…2],所以我们在求ex[1]=的时候根本没必要从s1[1]开始匹配,可以直接从s1[4]开始匹配直到失配为止。

至此,我们引入关于s2的next数组进行辅助求解s1的ex数组,next数组的几何含义差不多像这样.红色部分代表这部分相等

二.用辅助next数组来进行拓展kmp求解ex数组
这实际上是一个递推的过程,我们现在假设要求ex[i],为进行递推,我们需要知道一些条件,对于每个下标k(0=<k<i) 都已知了ex[k],由这个我们可以得到每个k的匹配区间[st,ed] 其中st=k,ed=k+ex[k]-1,需要的条件便是这个最大的ed和其对应的匹配区间[st,ed]的起点st,假设我们已知了这些条件现在我们开始求i,

我们可以得到s2[0 … ed-st]=s1[st … ed],所以也就有
s2[i-st … ed-st]=s1[i … ed]

假设next[i-st]=len; 所以就有s2[i-st … i-st+len-1]=s2[0 … len-1].
很明显这里我们要根据i+len-1与ed的位置关系来讨论才能求解ex[i];如下图所示,相同颜色的部分代表这一区间相匹配

第一种情况:i+len-1==ed,此时我们的位置就好像这样,不用说 ,由于不清楚ed后一位的匹配情况,因此我们要从s2[len]和s1[i+len]继续往后匹配,len=ed+1-i;,这时所有的图中匹配区间长度都相等

第二种情况:i+len-1>ed ,和第一种情况一样 也不知道ed后面的情况所以还要从s1的ed后开始匹配

第三种情况:i+len-1<ed时,那么我们就可以确定其匹配长度就是len,因为假设们匹配长度为len+1,那么就得到了s1[i … i+len]=s2[0 … len],而我们的s1[i … i+len]=s2[i-st … i-st+len ] ,从而推出
s2[0 … len]=s2[i-st … i-st+len ],即next[i-st]=len+1; 和我们的假设冲突。

所以我们就求解出了s1的ex数组,而s2的next数组的求法,其实本质和s1的ex数组求法一致,我们可以把s2看作母串,s2的每个后缀看为新的子串,那么就相当于求解母串的ex数组,而我们求第i个时又只需要知道i-1之前的信息,这样就可以把ex数组求出来,这就是s2的next数组。
例题:hdu2328
AC代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<time.h>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<functional>
#include<stack>
#include<map>
#include<queue>
#define mod (1000)
#define middle (l+r)>>1
#define SIZE 10000000+10
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double lb;
const int inf_max = 0x3f3f3f3f;
const ll Linf = 9e18;
const int maxn = 4000+10;
const long double e = 2.7182818;
const double eps=0.0001;
using namespace std;
int n;
char str[maxn][200+10],ex[210],nnext[210];
void mycopy(char ch[],int l,int r,char soc[])
{int cnt=0;for(int i=l;i<=r;i++)ch[cnt++]=soc[i];ch[cnt]='\0';
}
void exkmp_pre(char *s)
{int len=strlen(s);nnext[0]=len;int j=0,i=1;while(j+1<len&&s[j]==s[j+1]) ++j;nnext[i++]=j;int st=1;while(i<len) {int ed=st+nnext[st]-1;int L=nnext[i-st];   //L表示从母串i位置开始,子串0位置开始已经匹配好了的长度if(i+L<ed+1) nnext[i]=L;else {j=max(0,ed-i+1);while(j+i<len&&s[j+i]==s[j]) ++j;nnext[i]=j;st=i;}i++;}
}
bool exkmp(char *s1,char *s2)   //s1作为母串进行exkmp
{memset(ex,0,sizeof(ex));int len1=strlen(s1),len2=strlen(s2);int j=0;while(j<len2&&j<len1&&s1[j]==s2[j]) ++j;ex[0]=j;if(j==len2) return true;//printf("j=%d\n",j);int st=0;for(int i=1;i<len1;i++) {int ed = ex[st]+st-1;int L = nnext[i-st];if(i+L < ed+1) ex[i]=L;   //为什么是ed+1?因为如果等于i+L-1==ed时下标为ed的后一位就可能继续匹配了,所以这时候ex[i]有两种可能 ex[i]==ed||ex[i] > ed;所以要归到下种case判断else {j=max(0,ed+1-i);while(i+j<len1&&j<len2&&s1[i+j]==s2[j]) ++j;ex[i]=j;if(ex[i]==len2) return true;st=i;}}return false;
}
char ans[210];
int main()
{char ch1[210]="abab",ch2[210]="babab";exkmp_pre(ch1);exkmp(ch2,ch1);while(scanf("%d",&n),n){ans[0]='0';ans[1]='\0';int minv=inf_max,pos;for(int i=1;i<=n;i++) {scanf("%s",str[i]);if(minv>strlen(str[i])) {minv=strlen(str[i]);pos=i;}}int Max=0;for(int i=0;i<strlen(str[pos]);i++) {for(int j=i;j<strlen(str[pos]);j++) {memset(nnext,0,sizeof(nnext));char son[210];mycopy(son,i,j,str[pos]);bool flag=true;if(strlen(son)<Max) continue;  //剪枝exkmp_pre(son);for(int k=1;k<=n;k++) {if(k==pos) continue;if(!exkmp(str[k],son)) {flag=false;break;}  //如果有一个字符串不包含这个字串 那么这个不是可能的答案}if(flag) {  //如果这个子串是一个可能的答案//printf("ans=%s\n",ans);int now=j+1-i;if(now==Max) { //保留字典序最小的if(strcmp(ans,"0")==0||strcmp(ans,son)>0) strcpy(ans,son);}else if(now>Max) {Max=now;strcpy(ans,son);}}}}if(Max==0) printf("IDENTITY LOST\n");else printf("%s\n",ans);}return 0;
}

参考:
https://blog.csdn.net/qq_40160605/article/details/80407554
https://blog.csdn.net/dyx404514/article/details/41831947

拓展kmp(2020新年第一篇博客 学无止境冲啊)相关推荐

  1. 【新年第一篇博客】自己完成的第一款游戏 FlappyBird

    游戏简介 <flappy bird>是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品,游戏于2013年5月24日上线,并在2014年2月突然暴红.2014年2月,< ...

  2. 2020年我的第一篇博客日报

    博客日报缘由 谈起博客我们常想到CSDN.博客园.github等 谈起日报.周报我们自然想到了,工作工作工作... 但是谈起博客日报,那又是什么呢? "博客日报"不知道有没有这个词 ...

  3. 2020/12/10 大鲨鱼的第一篇博客

    我的第一篇博客 Markdown学习 标题 三级标题 四级标题 字体 你好,大鲨鱼 你好,大鲨鱼 你好,大鲨鱼 你好,大鲨鱼 引用 大鲨鱼永远永远永远是最棒的 分割线 图片 [外链图片转存失败,源站可 ...

  4. C博客作业00--我的第一篇博客

    这个作业属于哪个班级 C语言–网络2011/2012 这个作业的地址 C博客作业00–我的第一篇博客 这个作业的目标 学习Makdown语法,对本专业及C语言课程有个简单了解,记录自学慕课视频的笔记. ...

  5. 林大计算机学子第一篇博客

    林大计算机学子第一篇博客 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页.如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下 ...

  6. 我的第一篇博客:Python爬取新浪财经股票页面 并用matplotlib可视化输出结果

    (由于疫情在家闲着,开学至少得等到四月份,便在上个星期动起了学习python的念头,凭借着大一C语言微薄的基础草草学习语法后便开始了学写爬虫.跟着教学视频爬了几个静态网站后便开始尝试爬动态网站,同时也 ...

  7. 特殊的日子诞生我的第一篇博客!

    我的第一篇博客在2020年10月1号诞生 文章目录 前言 一.本人简介 二.博客知识规划 1.校招经验 2.大数据方面技术分享 3.生活杂记 总结 前言 写博客的目的主要在于巩固一下学过的知识,也介绍 ...

  8. 2023年的第一篇博客

    这是2023年的第一篇博客,想写些技术以外的东西,顺便做下博客1.2月份的内容预告,2月底之前会更新完FPGA 20个例程篇的最后两个例程即OV7725摄像头采集送显HDMI. RS232 USB L ...

  9. 蒟蒻的第一篇博客CF1041C Coffee Break(二分+贪心+set)

    CF1041C Coffee Break(二分+贪心+set) 描述 Recently Monocarp got a job. His working day lasts exactly mm min ...

最新文章

  1. 7、恢复数据库(mysql命令)
  2. mpc 安全多方计算协议_BNC公链 | 不看到数据却能进行计算?一文了解安全多方计算...
  3. ElasticSearch-Hadoop:从Hadoop到ElasticSearch索引产品视图计数和客户顶部搜索查询
  4. WPF学习笔记-第二周【基本笔刷】
  5. mysql必知必会_MySQL必知必会
  6. 单目摄像机测距(python+opencv)(转载)
  7. 在单位用oracle备份到磁带的脚本(看不明白的地方交流)
  8. 列表视图案例2——显示用户列表
  9. OpenGL在MFC下编程原理
  10. 编写HTML代码常见错误以及解决方法?
  11. 阶段3 1.Mybatis_09.Mybatis的多表操作_5 完成user的一对多查询操作
  12. 网页回到顶部的js代码实现
  13. java记账软件开发_Java项目之家庭记账软件
  14. ubuntu Nvidia 显卡驱动失效问题
  15. 离线脱机版个人笔记软件的选择
  16. 透过容抗来看电容量和频率的关系
  17. hadoop面试题 5 ---有用
  18. 前端加密 后端Java解密
  19. 论文笔记之---Person Re-identification in the Wild
  20. 字母数字特殊字符部分unicode对照表

热门文章

  1. Flask Web开发 3.0 模板
  2. Sequential Recommender Systems :Challenges, Progress and Prospects
  3. jre是否支持html5,html5的结构
  4. 如何用Python搭建一个搜题软件?
  5. 微信公众账号请求token次数达到上限(reach max api daily quota limit rid: 616fc6cc-1ddc78a8-3ea0a470)
  6. All in 区块链的百度昨日发布了白皮书,说了些什么?
  7. zepto移动端web相册
  8. 使用fiddler抓取HTTPS协议数据与疑难杂症终极解决方案
  9. VSRX防火墙安装与部署
  10. 云计算厂商们,你们辜负了中国的用户