网站开发自适应不同分辨率,主视觉设计网站,软文外链购买平台,品牌策划公司一般有什么职位P5829 【模板】失配树
题目#xff1a; 题解#xff1a;
参考题解 我们先想一个问题#xff1a;如何求出一个字符串的所有border#xff1f; 如果一个字符串既是 S的前缀又是 S 的后缀#xff0c;那么我们把 SS 自己平移一下就可以前后重合#xff0c;然后我们就可以继…P5829 【模板】失配树
题目 题解
参考题解 我们先想一个问题如何求出一个字符串的所有border 如果一个字符串既是 S的前缀又是 S 的后缀那么我们把 SS 自己平移一下就可以前后重合然后我们就可以继续匹。。。。。这不就是KMP吗 求两个前缀的最长公共border 先对原串进行KMP通过跳两个前缀的next求到两个前缀的所有border 我们通过next数组构建一棵树发现这就是只有一个字符串的AC自动机的fail树所有我们也叫它fail树容易发现两个前缀的最长公共border就是他们在fail树上的LCA
综上所述
对原串KMP一遍求的next数组构建fail树在fail数上跑LCA
代码
#includecstdio
#includeiostream
#includefstream
#includecmath
#includecstring
#includealgorithm
using namespace std;
#define Set(a) memset(a,0,sizeof(a))
#define F(i,a,b) for(register int ia,i##endb;ii##end;i)
#define UF(i,a,b) for(register int ia,i##endb;ii##end;--i)
#define openf(a) freopen(#a.in,r,stdin);freopen(#a.out,w,stdout)
#define re register
#define ri re int
#define il inline
typedef long long ll;
typedef unsigned long long ull;
templatetypename T inline T rd(T x)
{T f1;x0;char cgetchar();for(;!isdigit(c);cgetchar()) if(c-) f-1;for(; isdigit(c);cgetchar()) x(x3)(x1)(T)(c-0);x*f;return x;
}
ll rd(){ll x;rd(x);return x;}
inline int max(int a,int b){return ab?a:b;}
inline int min(int a,int b){return ab?a:b;}
const int inf130;const int N1000005;
int next[N],n,m;char s[N];
int fa[N];
int get(int x){return fa[x]x?x:fa[x]get(fa[x]);}
void merge(int x,int y){if((xget(x))!(yget(y)))fa[x]y;}
bool vis[N];
int head[N],to[2*N],nxt[2*N],tot;
void add(int u,int v){to[tot]v;nxt[tot]head[u];head[u]tot;}//graph
int head2[N],to2[2*N],nxt2[2*N],num[2*N],tot2;
void add2(int u,int v,int w){to2[tot2]v;num[tot2]w;nxt2[tot2]head2[u];head2[u]tot2;}//query
int ans[N],x[N],y[N];
void tarjan(int x)
{vis[x]true;for(ri ihead[x];i;inxt[i]) if(!vis[to[i]]) {tarjan(to[i]);merge(to[i],x);}for(ri ihead2[x];i;inxt2[i]) if(vis[to2[i]]) ans[num[i]]get(to2[i]);
}
int main()
{scanf(%s,s1);nstrlen(s1);next[0]next[1]0;F(i,1,n) fa[i]i;for(ri i2,j0;in;i){while(j!0s[j1]!s[i]) jnext[j];if(s[j1]s[i]) j;next[i]j;}F(i,1,n) add(next[i],i);rd(m);F(i,1,m){rd(x[i]);rd(y[i]);add2(x[i],y[i],i);add2(y[i],x[i],i);}tarjan(0);F(i,1,m) printf(%d\n,(ans[i]x[i]||ans[i]y[i])?next[ans[i]]:ans[i]);return 0;
}