您的位置:首页 > 其它

NOI2011 阿狸的打字机

2015-08-03 12:00 302 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=2434

AC自动机。

首先第1行的输入就是让我们建AC自动机。。。。。。(提示好大)

记第i个字符串在AC自动机里面的点编号为pos[i]。

其实询问就是:对于在AC自动机里pos[y]到根的路径上的所有结点,有多少个在fail-tree中在以pos[x]为根的子树中。

我们可以先在fail-tree中DFS,求出每个点i的DFS序idx[i],子树中最小的DFS序l[i]和子树中最大DFS序r[i],并建立树状数组。

然后在AC自动机里DFS,访问点i就在idx[i]位置+1,离开点i就在idx[i]位置-1,这样就是维护了点i到根的路径上的所有结点。

然后在树状数组里询问即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj

using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
{
int res=0;bool neg=0;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return 0;
if(z=='-'){neg=1;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=0;bool neg=0;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return 0;
if(z=='-'){neg=1;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
return (neg)?-res:res;
}

const int maxN=100000;
const int maxM=100000;
const int maxlen=100000;

int N,M;
char s[maxlen+100];
int pos[maxN+100];

int now,first[maxlen+100];
struct Tedge{int v,next;}edge[maxlen+100];

inline void addedge(int u,int v)
{
now++;
edge[now].v=v;
edge[now].next=first[u];
first[u]=now;
}

int cnt,fa[maxlen+100],fail[maxlen+100],ch[maxlen+100][30];
int head,tail,que[maxlen+100];
inline void build()
{
int i,p;
cnt=p=1;
fa[1]=0;
int len=strlen(s+1);
re(i,1,len)
if(s[i]=='B')
p=fa[p];
else if(s[i]=='P')
pos[++N]=p;
else
{
if(!ch[p][s[i]-'a'])ch[p][s[i]-'a']=++cnt,fa[cnt]=p;
p=ch[p][s[i]-'a'];
}
mmst(first,-1);now=-1;
fail[que[head=tail=1]=1]=1;
while(head<=tail)
{
int u=que[head++];
re(i,0,25)if(ch[u][i])
{
int v=ch[u][i];
if(u==1)
fail[que[++tail]=v]=1;
else
{
int temp=fail[u];
while(temp!=1 && !ch[temp][i])temp=fail[temp];
if(ch[temp][i])temp=ch[temp][i];
fail[que[++tail]=v]=temp;
}
addedge(fail[v],v);
}
}
}

int ge,idx[maxlen+100],l[maxlen+100],r[maxlen+100];

int top,sta[maxlen+100],last[maxlen+100];
inline void DFS1()
{
idx[sta[top=1]=1]=ge=1;
last[top]=first[1];
while(top>=1)
{
int u=sta[top],i=last[top],v;
for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)
{
idx[sta[++top]=v]=++ge;
last[top]=first[v];
last[top-1]=edge[i].next;
break;
}
if(i==-1)
{
l[u]=r[u]=idx[u];
for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)upmin(l[u],l[v]),upmax(r[u],r[v]);
top--;
}
}
}

#define lowbit(a) ((a)&(-(a)))
int tree[maxlen+100];
inline void update(int a,int v){for(;a<=cnt;a+=lowbit(a))tree[a]+=v;}
inline int ask(int l,int r)
{
int res=0;
for(;r>=1;r-=lowbit(r))res+=tree[r];
for(l--;l>=1;l-=lowbit(l))res-=tree[l];
return res;
}

vector<PII> Q[maxlen+100];
int ans[maxM+100];

inline void DFS2()
{
sta[top=1]=1;
last[top]=0;
while(top>=1)
{
int u=sta[top],i=last[top],v,j;
for(v=ch[u][i];i<26;i++,v=ch[u][i])if(v)
{
sta[++top]=v;
last[top]=0;
last[top-1]=i+1;
update(idx[v],1);
re(j,0,int(Q[v].size())-1)
{
int x=Q[v][j].fi,w=Q[v][j].se;
ans[w]=ask(l[x],r[x]);
}
break;
}
if(i==26)update(idx[u],-1),top--;
}
}

int main()
{
freopen("type.in","r",stdin);
freopen("type.out","w",stdout);
int i;
scanf("%s\n",s+1);
build();
M=gint();
re(i,1,M)
{
int x=gint(),y=gint();
Q[pos[y]].push_back(PII(pos[x],i));
}
DFS1();
DFS2();
re(i,1,M)PF("%d\n",ans[i]);
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: