扩展KMP笔记
KMP能计算一个字符串的每个位置前最长公共前缀后缀
扩展KMP可以用来计算两个字符串间的最长公共前缀后缀的……
不过为了计算这个需要绕些弯路
已知字符串$S$和$P$,$S$的长度为$n$,$P$的长度为$m$
扩展KMP实际是计算$E$数组,设$E[i]$为字符串$S[i..n-1]$与字符串$P$的最大公共前缀
尝试数学归纳法
$E[0]$显然只能直接依次比对,因为什么信息都没有
假设$E[0]\sim E[i-1]$都计算出来了,现在计算$E[i]$
不妨= =,利用$E[i-1]$的信息,第二行的矩形的宽度表示$E[i-1]$,只有这个信息是不够的,否则计算$E[i]$还是需要重复跑计算$E[i-1]$跑过的距离
假设有“$P[i..m-1]$与$P$的最大公共前缀长度”的信息,设为$N[i]$
- 如果$i\geqslant (i-1)+E[i-1]$,说明上个信息对这个没帮助,直接往右跑
- 如果$i+N[1]\geqslant (i-1)+E[i-1]$,由于红线右边的P与S是否相等不确定,因此要舍去红线右边的部分,那么经过如图的变形(第三排和第四排的矩形),可以直接从上一次失败的地方继续(红线处)
- 如果$i+N[1]<(i-1)+E[i-1]$,因为在红线前就失败了,那么直接就可以得到$E[i]=N[1]$
由于第一种情况中仍然可能重复对比$S$和$P$,$E[i-1]$可能不是最好的选择,那么我们就选红线最靠右的$E[k]$来计算$E[i]$
- 如果$i\geqslant j$,说明上个信息对这个没帮助,直接往右跑
- 如果$i+N[i-k]\geqslant j$,由于红线右边的P与S是否相等不确定,因此要舍去红线右边的部分,那么经过如图的变形(第三排和第四排的矩形),可以直接从上一次失败的地方继续(红线处)
- 如果$i+N[i-k]< j$,因为在红线前就失败了,那么直接就可以得到$E[i]=N[i]$
这样,在知道$N[i]$的情况下,可以$\mathcal{O}(n)$得到$E$数组(因为S与P的比较不会重复),前两种情况可以合并为一个,并且可以省去单独计算$E[0]$
代码:
inline void getE() {
int k = 0, j=0;
REP(i,0,n) {
if( i>=j || i+N[i-k] >= j ) {
if( i>=j ) j=i;
while( j < n && j - i < m && s[j] == p[j-i]) j++;
E[i] = j-i;
k = i;
} else {
E[i] = N[i-k];
}
}
}
对于$N$数组,和求$E$数组类似
$N[0]=m$,$N[1]$直接计算,假设$N[0]\sim N[i-1]$都求出来了,选红线最靠右的$N[k]$,那么
- 如果$i\geqslant j$,说明上个信息对这个没帮助,直接往右跑
- 如果$i+N[i-k]\geqslant j$,那么直接从上一次失败的地方继续(红线处)
- 如果$i+N[i-k]< j$,因为在红线前就失败了,那么$N[i]=N[i-k]$
代码:
inline void getN() {
int k = 0, j=0;
N[0] = m;
REP(i,1,m) {
if( i>=j || i+N[i-k] >= j ) {
if( i>=j ) j=i;
while( j < m && p[j] == p[j-i]) j++;
N[i] = j-i;
k = i;
} else {
N[i] = N[i-k];
}
}
}
HDU-2594
题目
给两个字符串,第一个字符串与第二个字符串的最长公共前缀后缀
题解
直接套用EXKMP第一个字符串设为p,第二个字符串设为s,找到第一个i,使E[i]=n-i,就可以了
AC代码
#include<cstdio>
#include<cstring>
#include<cassert>
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__),fflush(stdout)
#else
#define DBG(...) (void)0
#endif // sahdsg
using namespace std;
#define REP(r,x,y) for(register int r=(x); r<(y); r++)
#define MAXN 50007
char p[MAXN], s[MAXN];
int N[MAXN], m;
int E[MAXN], n; inline void getN() {
int k = 0, j=0;
N[0] = m;
REP(i,1,m) {
if( i>=j || i+N[i-k] >= j ) {
if( i>=j ) j=i;
while( j < m && p[j] == p[j-i]) j++;
N[i] = j-i;
k = i;
} else {
N[i] = N[i-k];
}
}
} inline void getE() {
int k = 0, j=0;
REP(i,0,n) {
if( i>=j || i+N[i-k] >= j ) {
if( i>=j ) j=i;
while( j < n && j - i < m && s[j] == p[j-i]) j++;
E[i] = j-i;
k = i;
} else {
E[i] = N[i-k];
}
}
} int main() {
#ifdef sahdsg
freopen("in.txt", "r", stdin);
#endif // sahdsg
while(~scanf("%s%s", p,s)) {
n=strlen(s),m=strlen(p);
getN();
getE();
int t=-1;
// REP(i,0,n) DBG("%d ", E[i]);
REP(i,0,n) {
if(E[i]==n-i) {
t=i;
break;
}
}
if(~t) {
printf("%s %d\n", s+t, n-t);
} else puts("0");
} return 0;
}
扩展KMP笔记的更多相关文章
- HDU 4333 Revolving Digits [扩展KMP]【学习笔记】
题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如 ...
- 扩展kmp学习笔记
kmp没写过,扩展kmp没学过可还行. 两个愿望,一次满足 (该博客仅用于防止自己忘记,不保证初学者能看懂我在瞎bb什么qwq) 用途 对于串\(s1,s2\),可以求出\(s2\)与\(s1\)的每 ...
- 扩展KMP算法
一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...
- 扩展KMP --- HDU 3613 Best Reward
Best Reward Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...
- KMP和扩展KMP
文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...
- UVA5876 Writings on the Wall 扩展KMP
扩展KMP的简单题. #include<stdio.h> #include<string.h> #define maxn 51010 char s[maxn],t[maxn]; ...
- hdu4333 扩展KMP
慢慢研究可以发现,可以用扩展kmp来求.由于扩展kmp的next[]只有一部分,当前位子前面那部分和母串的后部分,所以可以将字符串复制接在后面一次. 先求如果next[]>0&& ...
- 扩展KMP
刘雅琼论文 http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 论文讲的非常详细. 给定母串S,子串T,n=strlen(S),m=st ...
- HDU 3336 扩展kmp
题目大意: 找到字符串中所有和前缀字符串相同的子串的个数 对于这种前缀的问题,通常通过扩展kmp来解决 其实吧这是我第一次做扩展kmp的题目,原来确实看过这个概念,今天突然做到,所以这个扩展kmp的模 ...
随机推荐
- DevExpress MVVM<1>
DevExpress MVVM 概念 模型 -定义数据和您的业务逻辑. 视图 -指定UI,包括绑定到ViewModel中的属性和命令的所有可视元素(按钮,标签,编辑器等). ViewModel-连接模 ...
- Android 无源码smail进行debug
待调试项目在AndroidManifest.xml中debugable=true 参照此处:https://blog.csdn.net/ausboyue/article/details/8018918 ...
- JDK8,Optional
作为程序员,你肯定遇到过NullPointerException, 这个异常对于初出茅庐的新人, 还是久经江湖的老手都是不可避免的痛, 可又是那么的无能为力,为了解决它,你只能在使用某个值之前,对其 ...
- SAP之RFC_READ_TABLE
RFC_READ_TABLE 是SAP系统自带的RFC函数,用于读取SAP数据库表的结构和数据.使用方法如下: IMPORTINGQUERY_TABLE:读取的表名DELIMITER:输出字段(DAT ...
- Office2019新增哪些功能
上一篇文章我们知道了office为什么没有2017/2018版本,那个是因为微软office是时隔三年一更新的软件,这不office2019就出来了.一款软件,只有不断的完善自身功能,进行不断的更新, ...
- Codeforces 7E - Defining Macros 题解
目录 Codeforces 7E - Defining Macros 题解 前言 做法 程序 结尾 Codeforces 7E - Defining Macros 题解 前言 开始使用博客园了,很想写 ...
- Community structure enhanced cascade prediction 笔记
目录 一.摘要 二.杂记 三.模型思想 四.实验 五.其他 六.参考文献 一.摘要 深度学习不用去手工提取特征,但是现有深度模型没有在传播预测任务中使用社区结构.所以提出一个CS-RNN框架,把社区在 ...
- 28.分类算法---KNN
1.工作原理: 存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类对应的关系.输入没有标签的数据后,将新数据中的每个特征与样本集中数据对应的特 ...
- pytorch 中的Variable一般常用的使用方法
Variable一般的初始化方法,默认是不求梯度的 import torch from torch.autograd import Variable x_tensor = torch.randn(2, ...
- 关于python的中国历年城市天气信息爬取
一.主题式网络爬虫设计方案(15分)1.主题式网络爬虫名称 关于python的中国城市天气网爬取 2.主题式网络爬虫爬取的内容与数据特征分析 爬取中国天气网各个城市每年各个月份的天气数据, 包括最高城 ...