[复习] border 与 单模式匹配 KMP 算法

[复习] KMP

前缀函数

Si 为字符串 S 的第 i 个位置。

我们设 π(i) 表示字符串以 i 结尾的前缀的最长公共前后缀的长度,也记作 border

这里的前后缀都指的是真前缀、真后缀。

怎么 O(n) 求出 π(i)

性质:相邻的 π 至多增加 1。

因此, 若 s[π(i)+1]=s[i+1] 时,π(i+1)=π(i)+1

如果失配,我们要找到 i 前缀的第二长的公共前后缀,然后再次比较。以此类推。

那么

[s1s2s3s4]...[si3si2si1si]si+1

如果 π(i)=4,即 s[1...4]=s[i3...i]

而第二长的公共前后缀长度 j,假如 j=2,那么 s[1...2]=s[i1...i]

由于 s[1...4]=s[i3...i],那么 s[i1...i]=s[3...4],所以 s[1...2]=s[3...4]

所以第二长的公共前后缀长度是前缀 π(i) 的最长公共前后缀长度,即 π(π(i))

所以如果 π(i)+1 失配,那么就找到 π(π(i))+1,然后是 π(π(π(i)))+1

到最后找到 1,若不相等则 π(i+1)=0

核心代码:

nx[1]=0;
for(int i=2;i<=len;i++){
int j=nx[i-1];
while(j>0&&s[j+1]!=s[i])j=nx[j];
if(s[i]==s[j+1])++j;
nx[i]=j;
}

KMP 算法

对于文本串 s 和模式串 t 匹配,可以求出字符串 t+#+s 的前缀函数,其中 # 是一个额外字符,然后就能知道 s 每个前缀能否与 t 匹配。

fail 树

AC 自动机中的定义和这里类似。

我们把 π(i) 连向 i,这样就得到一棵以 0 为根的树,称作 fail 树。

性质:显然的,在 fail 树上,一个点 i 的所有祖先都是 iborder
或者说,jiborder 当且仅当 ji 的祖先。

最长公共 border

对于两个前缀 i,j(ij),它们的最长公共 border,就是 ijfail 树上的 LCA

posted @   dengchengyu  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示