Z 函数(扩展KMP)
简介
定义一个长度为 的字符串 ,定义 表示 和 的 (最长公共前缀),称 为 的 函数。
朴素算法
暴力枚举,时间复杂度:
线性算法
我们首先考虑顺次处理 ,当枚举到 时,也就是说 是已经求得了。
我们再来定义名词 Z-box :指与字符串 匹配的前缀区间,同时满足包含 (当枚举到 时)且右端点最大。
首先我们来考虑如何更新这个 Z-box (分类讨论):
-
设 为左端点( 的 Z-box), 为右端点( 的 Z-box), 为当前枚举的点。
-
当 时,那也就是上一个 Z-box 对于 时没有用处的,那就从 开始,暴力向后匹配求得 Z-box
-
当 时,分两种情况:
-
那么 (图标可能有点问题,以公式为准!!!)
-
那么 ,但是后面的匹配不能保证所以就向后匹配即可。
-
时间复杂度证明
枚举 是 的, 会一直向后移动也是 的,所以总的来说是 的。
代码实现
inline void getz()
{
for(int i=1;i<=m;i++)z[i]=0;
z[1]=m;
for(int i=2,l=0,r=0;i<=m;i++)
{
if(i<=r)z[i]=min(z[i-l+1],r-i+1);
while(i+z[i]<=m&&b[i+z[i]]==b[z[i]+1])++z[i];
if(r<i+z[i]-1)l=i,r=i+z[i]-1;
}
}
同时这个也可拓展到两个串的匹配( 与 的每一个后缀的 ),代码实现:
inline void getext()
{
for(int i=1;i<=n;i++)ext[i]=0;
for(int i=1,l=0,r=0;i<=n;i++)
{
if(i<=r)ext[i]=min(z[i-l+1],r-i+1);
while(i+ext[i]<=n&&b[ext[i]+1]==a[i+ext[i]])++ext[i];
if(r<i+ext[i]-1)l=i,r=i+ext[i]-1;
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库