打击目标 - 可持久化Trie

题目大意:
给你一颗树,每个点有一个字符串,多次强制在线询问一条路径以及一个字符串,问路径上所有点的字符串是询问串子串的最长长度。
n , q 1 0 5 , S 1 0 6 n,q\le 10^5,\sum|S|\le10^6
题解:
(原题还有一个限制时每个点的字符串长度不超过10,所以拟可以直接枚举答案可持久化Trie一波……)
可以建AC自动机,每次询问再上面匹配然后每到一个点就询问其到根的路径上是否有在路径上的点,直接树剖和主席树维护一下就好了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define N 100010
#define LEN 13
#define SIG 26
#define LOG 20
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
char m[N][LEN],qs[N];
struct edges{
	int to,pre;
}e[N];int ncnt,ch[N*LEN][SIG],wd[N*LEN],T[N],up[N][LOG],Log[N],d[N],h[N],etop;
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
inline int ins(int &x,int y,char *s,int n)
{
	for(int z=x=++ncnt,i=1;i<=n;i++)
		(y?memcpy(ch[z],ch[y],sizeof ch[y]),wd[z]=wd[y]:0),
		z=ch[z][s[i]-'a']=++ncnt,y=ch[y][s[i]-'a'];
	memcpy(ch[ncnt],ch[y],sizeof ch[y]),wd[ncnt]=wd[y]+1;
	return 0;
}
int dfs(int x,int f=0)
{
	up[x][0]=f,d[x]=d[f]+1,ins(T[x],T[f],m[x],(int)strlen(m[x]+1));
	rep(i,1,Log[d[x]]) up[x][i]=up[up[x][i-1]][i-1];
	for(int i=h[x];i;i=e[i].pre) dfs(e[i].to,x);return 0;
}
inline int getLCA(int x,int y)
{
	if(d[x]<d[y]) swap(x,y);
	for(int i=Log[d[x]];i>=0;i--)
		if(d[up[x][i]]>=d[y]) x=up[x][i];
	if(x==y) return x;
	for(int i=Log[d[x]];i>=0;i--)
		if(up[x][i]^up[y][i]) x=up[x][i],y=up[y][i];
	return up[x][0];
}
inline int calc(int x,char *s,int n)
{
	for(int i=1;i<=n;x=ch[x][s[i]-'a'],i++)
		if(!ch[x][s[i]-'a']) return 0;return wd[x];
}
inline int check(char *s,int n,int a,int b,int c,int d)
{
	return calc(T[a],s,n)+calc(T[b],s,n)-calc(T[c],s,n)-calc(T[d],s,n);
}
int main()
{
	int n=inn(),qzzx=inn();
	rep(i,1,n) scanf("%s",m[i]+1);
	rep(i,2,n) add_edge(inn(),i),Log[i]=Log[i>>1]+1;
	dfs(1);
	for(int q=inn(),las_ans=0;q;q--)
	{
		int s=inn(),t=inn();
		if(qzzx) s^=las_ans,t^=las_ans;
		int c=getLCA(s,t),f=up[c][0];
		scanf("%s",qs+1);int qn=(int)strlen(qs+1),ans=0;
		for(int len=10;len;len--) rep(i,1,qn-len+1)
			if(check(qs+i-1,len,s,t,c,f)) { ans=len;goto loop; }
		loop:printf("%d\n",las_ans=ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82958142