扩展kmp学习笔记
kmp没写过,扩展kmp没学过可还行。
两个愿望,一次满足
(该博客仅用于防止自己忘记,不保证初学者能看懂我在瞎bb什么qwq)
用途
对于串\(s1,s2\),可以求出\(s2\)与\(s1\)的每个后缀的最长公共前缀。
(其实SA也可以干这事,只不过复杂度多个\(\log\)可能会被卡)
思想
与kmp一样,主要是充分利用已经得到的信息来往下推,以降低复杂度。
暴力
\(O(n^2)\)暴力扫,相信大家都会?
优化
记\(s[l,r]\)表示\(s\)在\([l,r]\)的子串。
考虑这样一件事:假如\(s2[1,k]=s1[1,k]\),那么就可以知道\(s2[2,k]=s1[2,k]\)。
假如再知道\(s2[2,p]=s2[1,p-1]\),那么就可以推出\(s2[1,\min(p,k)-1]=s1[2,k]\)了。
\(s2[2,p]=s2[1,p-1]\)正是kmp中\(s2\)的\(nxt\)数组,于是这样就可以完成一次转移。
然而这样转移并不是很优:当\(p<k\)时显然不能再往后推,但\(p>k\)时往后推还需要\(O(n)\)的时间,总复杂度仍然是\(O(n^2)\)的。
但我们可以记录之前最大的\(k\)在哪里,于是\(k_{max}\)单调递增,复杂度就有保证了。
代码
由于求nxt和求ex代码非常像,于是缩到了一起。
int n,m;
char s1[sz],s2[sz];
int nxt[sz],ex[sz];
void ExKmp(char *s1,char *s2,int *nxt,int *ex)
{
int len1=strlen(s1+1),len2=strlen(s2+1);
if (s1!=s2) for (ex[1]=0;s1[ex[1]+1]==s2[ex[1]+1]&&ex[1]<min(len1,len2);ex[1]++);
else {nxt[1]=len1;while (s1[nxt[2]+1]==s1[nxt[2]+2]&&nxt[2]+2<=len1) ++nxt[2];}
int p=1+(s1==s2);
rep(i,2+(s1==s2),len1)
{
if (i+nxt[i-p+1]<p+ex[p]) ex[i]=nxt[i-p+1];
else
{
int k=max(p+ex[p]-i,0);
while (s1[i+k]==s2[k+1]) ++k;
ex[i]=k;p=i;
}
}
}
int main()
{
file();
cin>>(s1+1)>>(s2+1);
n=strlen(s1+1),m=strlen(s2+1);
ExKmp(s2,s2,nxt,nxt);ExKmp(s1,s2,nxt,ex);
rep(i,1,m) printf("%d ",nxt[i]);
puts("");
rep(i,1,n) printf("%d ",ex[i]);
return 0;
}
扩展kmp学习笔记的更多相关文章
- 扩展kmp 学习笔记
学习了一下这个较为冷门的知识,由于从日报开始看起,还是比较绕的-- 首先定义 \(Z\) 函数表示后缀 \(i\) 与整个串的 \(lcp\) 长度 一个比较好的理解于实现方式是类似于 \(manac ...
- 126B Password[扩展kmp学习]
题目大意 给你一个字符串,求它的一个子串使得这个子串即使前缀又是后缀又出现在不是前缀且不是后缀的地方 分析 扩展kmp就是定义z[i]表示i~n的子串与整个串的最长公共前缀的长度是z[i] 所以这个题 ...
- KMP学习笔记
功能 字符串T,长度为n. 模板串P,长度为m.在字符串T中找到匹配点i,使得从i开始T[i]=P[0], T[i+1]=P[1], . . . , T[i+m-1]=P[m-1] KMP算法先用O( ...
- C#扩展方法学习笔记
C#扩展方法,简单的理解是不修改原来类的源代码的情况下,为某个类添加某个方法.扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的.它们的第一个参数指定该方法作用于哪个类型,并且该参数以 th ...
- Unity扩展编辑器学习笔记--从路径下找到拥有某个组件类型的预设
public static List<T> GetAssetsWithScript<T>(string path) where T:MonoBehaviour { T tmp; ...
- ReactiveX 学习笔记(0)学习资源
ReactiveX 学习笔记 ReactiveX 学习笔记(1) ReactiveX 学习笔记(2)创建数据流 ReactiveX 学习笔记(3)转换数据流 ReactiveX 学习笔记(4)过滤数据 ...
- Kuangbin 带你飞 KMP扩展KMP Manacher
首先是几份模版 KMP void kmp_pre(char x[],int m,int fail[]) { int i,j; j = fail[] = -; i = ; while (i < m ...
- Kotlin学习笔记(9)- 数据类
系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步! Kotlin学习笔记(1)- 环境配置 Kotlin学习笔记(2)- 空安 ...
- HDU 4333 Revolving Digits [扩展KMP]【学习笔记】
题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如 ...
随机推荐
- App功能测试点总结
1.手机操作系统android(谷歌).ios(苹果).Windows phone(微软).Symbian(诺基亚).BlackBerry OS(黑莓).windows mobile(微软),目前主流 ...
- SQL Server存储过程中字符串前加N的含义
使用方法: N'字符串' 解释: 意思为后面的数据类型为NChar或者NVarchar 使用N前缀 在服务器上执行的代码中(例如在存储过程和触发器中)显示的Unicode字符串常量必须以大写字母N为前 ...
- 数据结构之队列(queue)
队列介绍 1.队列是一个有序列表,可以用数组或是链表来实现. 2.遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的要后取出. 应用场景 比如某某银行叫号系统: 数组模拟队列 队列本身是有序 ...
- Linux查找文件之Find命令
Linux系统文件中常用属性包括以下内容:名称,大小,权限,属主,属组,修改时间,访问时间等.在庞大的Linux系统中查询文件,需要借助查找工具来实现,依此可以查询相同或指定属性的文件,本文所讲的查询 ...
- switch语句中 参数的类型
switch可作用于char byte short int switch可作用于char byte short int对应的包装类 switch不可作用于long double float boole ...
- Android studio如何连接三星手机
打开Android studio,选择Trouble Shoot device connections: 这个菜单项会自动扫描本地已经用USB线连接的设备: 已经成功扫描出了我的Galaxy C7 P ...
- HttpContext & HttpRuntime
问题引出 HttpContext.Current.Cache .VS. HttpRuntime.Cache HttpRuntime.Cache:获取当前应用程序的Cache HttpContext.C ...
- 分布式Hadoop和HBase整合
环境: CentOS 6.6 hadoop-2.6.0 hbase-0.98.10.1 HBase1 192.168.1.4 Mast ...
- IAR 为 STM32新建工程模板(最详细)
今天给小伙伴分享一篇给stm32新建工程模版 1.首先打开IAR,就是这个样子 2.再建一个目录文件夹 3.建立一个工作空间,以及建好工作空间如右图所示 4.接下来建立工程,Project------ ...
- Oracle基础知识【1】
目录: 1.Oracle创建库.表 2.Oracle数据怎删查改操作 3.Oracle数据约束条件 Oracle创建库.表: create user user05 identified by 1234 ...