8
10
2016
0

[BZOJ3483] SGU505 Prefixes and suffixes(询问在线版)

考虑维护可持久化线段树+字典树

首先建出两个字典树(一正一反),求一下dfs序然后就变成了查询当前字符串在这两个字典树中区间的共有值

我们可以利用可持久化线段树来支持查询

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=2005,M=2000005;

int n,ans,len,posA[N],posB[N],root[N*25],l[N*25],r[N*25],v[N*25],cnt,en,h[M],m;
char s[M],ch;

inline void Read_Decrypt(){
while((ch=getchar())<'a' || ch>'z');
s[len=1]=(ch-'a'+ans)%26;
while((ch=getchar())>='a' && ch<='z')s[++len]=(ch-'a'+ans)%26;
}

struct Edge{
int b,next;
}e[N];

inline void AddEdge(int sa,int sb){e[++en].b=sb;e[en].next=h[sa];h[sa]=en;}

struct Trie{
int son[M][26],cnt,dfn,st[M],ed[M];
inline int ins0();
inline int ins1();
void dfs(int x);
inline pair<int,int> ask0();
inline pair<int,int> ask1();
}A,B;

inline int Trie::ins0(){
int x=0;
for(int i=1;i<=len;i++){
	if(!son[x][s[i]])son[x][s[i]]=++cnt;
	x=son[x][s[i]];
}
return x;
}

inline int Trie::ins1(){
int x=0;
for(int i=len;i;i--){
	if(!son[x][s[i]])son[x][s[i]]=++cnt;
	x=son[x][s[i]];
}
return x;
}

void Trie::dfs(int x){
st[x]=++dfn;
for(int i=0;i<26;i++)if(son[x][i])dfs(son[x][i]);
ed[x]=dfn;
}

inline pair<int,int> Trie::ask0(){
int x=0;
for(int i=1;i<=len;i++){
	if(!son[x][s[i]])return make_pair(0,0);
	x=son[x][s[i]];
}
return make_pair(st[x],ed[x]);
}

inline pair<int,int> Trie::ask1(){
int x=0;
for(int i=len;i;i--){
	if(!son[x][s[i]])return make_pair(0,0);
	x=son[x][s[i]];
}
return make_pair(st[x],ed[x]);
}

inline int Insert(int x,int a,int b,int p){
int y=++cnt;v[y]=v[x]+1;
if(a==b)return y;
int mid=a+b>>1;
if(p<=mid)l[y]=Insert(l[x],a,mid,p),r[y]=r[x];
else l[y]=l[x],r[y]=Insert(r[x],mid+1,b,p);
return y;
}

inline int Query(int x,int a,int b,pair<int,int> p){
if(!x)return 0;
if(p.first<=a && b<=p.second)return v[x];
int mid=a+b>>1,ans=0;
if(p.first<=mid)ans+=Query(l[x],a,mid,p);
if(p.second>mid)ans+=Query(r[x],mid+1,b,p);
return ans;
}

int main(){
freopen("3483.in","r",stdin);
freopen("3483.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++){
    Read_Decrypt();
    posA[i]=A.ins0();posB[i]=B.ins1();
}
A.dfs(0);B.dfs(0);
for(int i=1;i<=n;i++)AddEdge(A.st[posA[i]],B.st[posB[i]]);
for(int i=1;i<=A.dfn;i++){
	root[i]=root[i-1];
	for(int j=h[i];j;j=e[i].next)root[i]=Insert(root[i],1,B.dfn,e[j].b);
}
scanf("%d",&m);
while(m--){
    pair<int,int> L,R;
    Read_Decrypt();
    L=A.ask0();
    Read_Decrypt();
    R=B.ask1();
    if(L.first && R.first)ans=Query(root[L.second],1,B.dfn,R)-Query(root[L.first-1],1,B.dfn,R);
    else ans=0;
    printf("%d\n",ans);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 719

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com