失配树学习笔记

文章介绍了失配树(fail树)的概念,它是利用KMP和LCA算法解决求两个前缀最长公共Border问题的数据结构。主要讨论了Border的定义、失配树的构建方法以及在实际问题中的应用,包括计算两个区间前缀的LCA和处理特殊情况的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

失配树,是一种奇妙的数据结构,它利用 KMP、LCA 解决求两前缀的最长公共 Border 的问题。

首先介绍一下什么是 Border,我们知道 nxt 数组是前后缀相同的最大长度,Border 相当于是 nxt 数组的弱化版,只是去掉了“最大”的限制。

我们考虑如何建立一棵失配树(fail 树),对于每一个长度为 i i i 的前缀,我们预处理出它的 nxt,然后按照 i i i 指向 nxt[i],即 nxt[i] i i i 的爹。

对于两个前缀的最长 Border,我们只需要对于两个区间的 i i i j j j 求出它们的 LCA 即可。这里需要注意一个坑,如果 i i i j j j 的 LCA 是他们中的一个,那么我们要把 LCA 上提一步,即返回 f[i][0]f[j][0](返回他们的父亲)。


练手板子题

代码如下:

#include <bits/stdc++.h>
using namespace std;

const int maxn=1e6+5;
char s[maxn];
int f[maxn][25],dep[maxn];

int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=20;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
	if(x==y) return f[x][0];
	for(int i=20;i>=0;i--)
		if(f[x][i]!=f[y][i])
			x=f[x][i],y=f[y][i];
	return f[x][0];
}

int main()
{
	scanf("%s",s+1);
	int len=strlen(s+1);
	f[0][0]=f[1][0]=0;dep[0]=0;dep[1]=1;
	for(int i=1,j=0;i<=len;i++)
	{
		while(j&&s[i+1]!=s[j+1]) j=f[j][0];
		if(s[i+1]==s[j+1]) j++;
		f[i+1][0]=j,dep[i+1]=dep[j]+1;
	}
	int m;cin>>m;
	for(int j=1;j<=20;j++) for(int i=1;i<=len;i++) f[i][j]=f[f[i][j-1]][j-1];
	while(m--)
	{
		int p,q;cin>>p>>q;
		cout<<lca(p,q)<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值