Jzoj4348 打击目标

又是被水题坑了。。。

一直想不出来看题解说要什么主席树,于是开始打离线算法

结果打到一半发现要强制在线。。No!!!

发现直接AC自动机似乎可做?树剖之后在AC自动机上跑的时候判断一下不就好了吗!连线段树都不要

让后快乐切掉,速度还可以(废话,人家N^2暴力都跑得飞快)

#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define vs (*s-'a')
#define N 100010
using namespace std;
struct AcAutomation{
	int son[N*10][26],f[N*10],c[N*10],cnt;
	queue<int> q; vector<int> p[N*10];
	inline void clear(){ cnt=1; }
	inline void insert(char* s,int pos){
		int x=1,l=0;
		for(;*s;++s,++l)
			x=son[x][vs]?son[x][vs]:son[x][vs]=++cnt;
		c[x]=l; p[x].push_back(pos);
	}
	inline void build(){
		p[1].push_back(N); sort(p[1].begin(),p[1].end());
		for(int i=0;i<26;++i)
			if(!son[1][i]) son[1][i]=1;
			else q.push(son[1][i]),f[son[1][i]]=1;
		for(int x;!q.empty();q.pop()){
			x=q.front(); p[x].push_back(N);
			sort(p[x].begin(),p[x].end());
			for(int i=0;i<26;++i)
				if(!son[x][i]) son[x][i]=son[f[x]][i];
			else q.push(son[x][i]),f[son[x][i]]=son[f[x]][i];
		}
	}
	inline int query(char* s,int l,int r){
		int ans=0;
		for(int x=1;*s;++s){
			x=son[x][vs];
			for(int j=x;j>1;j=f[j])
				if(c[j]>ans && *lower_bound(p[j].begin(),p[j].end(),l)<=r)
					{ ans=c[j]; break; }
		}
		return ans;
	}
}AC;
char s[N][12],c[N];
struct edge{ int v,nt; } G[N<<1];
int h[N],d[N],f[N],top[N],son[N],sz[N];
int l[N],r[N],n,m,cnt=0,clk=0,T;
inline void adj(int x,int y){
	G[++cnt]=(edge){y,h[x]}; h[x]=cnt;
	G[++cnt]=(edge){x,h[y]}; h[y]=cnt;
}
void dfs(int x,int p){
	d[x]=d[p]+1; f[x]=p; sz[x]=1;
	for(int v,i=h[x];i;i=G[i].nt)
		if(!d[v=G[i].v]){
			dfs(v,x);
			sz[x]+=sz[v];
			if(sz[son[x]]<sz[v]) son[x]=v;
		}
}
void dgs(int x,int p){
	l[x]=++clk; top[x]=p; 
	if(son[x]) dgs(son[x],p);
	for(int v,i=h[x];i;i=G[i].nt)
		if(!top[v=G[i].v]) dgs(v,v);
}
int gLca(int x,int y,char* s){
	int ans=0;
	for(;top[x]!=top[y];y=f[top[y]]){
		if(d[top[x]]>d[top[y]]) x^=y^=x^=y;
		ans=max(ans,AC.query(s,l[top[y]],l[y]));
	}
	if(d[x]>d[y]) x^=y^=x^=y;
	return max(ans,AC.query(s,l[x],l[y]));
}
int main(){
	scanf("%d%d",&n,&T); AC.clear();
	for(int i=1;i<=n;++i) scanf("%s",s[i]);
	for(int x,i=2;i<=n;++i) scanf("%d",&x),adj(x,i);
	dfs(1,0); dgs(1,1);
	for(int i=1;i<=n;++i) AC.insert(s[i],l[i]);
	scanf("%d",&m); AC.build();
	for(int x,y,ans=0;m--;){
		scanf("%d%d%s",&x,&y,c);
		x^=ans; y^=ans; ans=gLca(x,y,c);
		printf("%d\n",ans); ans*=T;
	}
}


posted @ 2017-12-30 21:32  扩展的灰(Extended_Ash)  阅读(131)  评论(0编辑  收藏  举报