字符串一些算法总结
最近在补字符串
运用极不详尽,以后慢慢补
1|0KMP
算法讲解
我们要求的就是字符串a的每一个前缀的最长公共前后缀,设为s数组(也叫前缀函数)
例:
aaabbaaa
s:0,1,1,0,0,1,2,3
首先有一个显然的暴力,这个复杂度是
考虑快速维护,假设我们求出了
首先,
然后分类讨论,如果能直接匹配就匹配,为
然后,我们暴力从前面跳,考虑这样一个情形:
我们发现不能匹配,就想能否在
由于s每次最多增大1,而只有减小操作,所以时间复杂度为
运用
求一个串t在另一个串s中的出现的所有位置
设字符串
2|0Z函数(扩展kmp)
算法讲解
我们由一个字符串a,对于每一个位置i,求出
我们假设前面的z的最大右端点为r,对应的i为l
如果当前的i不在这个区间里,就暴力扩展然后更新l,r
如果在,根据lcp的性质,
为什么呢?首先,z在前面的区间内对应的位置是i-l,这个好理解,然后看z[i-l]的值
但这里会遇到一个情况,
我们就从
这样就是正确的
那么时间复杂度呢?由于内层扩展时r每次都会增加,而r不会减小,所以时间复杂度为
其实感觉过程更像manacher
运用
上面的kmp的也可以用z函数做
3|0manacher
算法讲解
我们考虑解决求一个字符串中的所有回文串
看上去没有线性解法
但是,以一个位置为中心,往两边扩展,必定能找到一个长度,使得长度以前的是回文,以后一定不是
那么,我们只要求出这个长度即可,设为数组h
而回文串有空位为中心的和位置为中心的,我们直接在位置之间插入一个特殊字符(即不是字符集里的),代表空位
显然,有hash的带
设我们已经求出了前面的所以h,r为最大的h+i,l为r对应的i
我们类似z函数,如果当前位置在这个区间外,就暴力扩展
否则,就可以在区间里找到一个对称的点,然后继承那个点的h,如果超过了区间,就从右端点开始暴力扩展,像z函数一样,如果不清楚看一下z函数
而时间复杂度的分析甚至也是一样的,由于内层的循环一定会带来r的增加,所以总时间复杂度为
运用
求上面的问题
4|0PAM(回文自动机)
算法讲解
我们想,可不可以把回文表示成自动机的形式,于是就有了PAM
像正常的自动机一样,PAM有两部分:自动机和树,具体来说,有
区别于manacher,由于结构好,我们可以直接搞两个跟,表示长度为奇数/偶数的根
我们考虑增量构造法,设把
然后我们还要求p的fail,就再次从
偶根的fail指向奇根,奇根不会失配,所以不重要
而只用加一个点的原因是如果最长的回文串被框出来了,那么次小的在前面也会有对应的串,已经被增加过,就可以不用重复添加
运用
可以解决本质不同回文串的个数问题,而manacher是无法判重的
__EOF__

本文链接:https://www.cnblogs.com/longzhaocheng/p/17921793.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】