题目大意:
给定一个串 S,定义 border 为它的非本身的既是它的前缀又是它的后缀的字符串,每次询问 i,j 求出前 i 个和前 j 个字符的最长公共 border 长度。
算法分析:
根据题目的描述,会发现这道题本质上是 KMP,求出每一个点的前缀和后缀匹配的长度,设为 kmp 数组。然后就是这道题的精髓。
这里需要建一个失配树,也就是每一个点的 kmp 数组向这个点连一条边。(个人感觉跟 AC 自动机的 fail 树有异曲同工之妙。)这时会发现,会建成一个树,父亲节点就是 kmp 数组的值,儿子节点就是该点。
最后,题目的要求相当于求两个点的 LCA,用倍增求即可。
注意细节,如果这两个点本身就有 border 关系,那么需要输出 dep 小的点的父亲节点。也很好实现,把倍增中的中途 x=y 返回删去,直接最后返回即可。
具体细节看代码吧。
总代码:
#include<bits/stdc++.h>
#define re register
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch&#