CodeForces 547E Mike and Friends [Fail树+树状数组]

来源:互联网 发布:逆波兰算法 编辑:程序博客网 时间:2024/05/21 02:20

Description

What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercase English letters. What is double strange that a phone number can be associated with several bears!

In that country there is a rock band called CF consisting of n bears (including Mike) numbered from 1 to n.

Phone number of i-th member of CF is si. May 17th is a holiday named Phone Calls day. In the last Phone Calls day, everyone called all the numbers that are substrings of his/her number (one may call some number several times). In particular, everyone called himself (that was really strange country).

Denote as call(i, j) the number of times that i-th member of CF called the j-th member of CF.

The geek Mike has q questions that he wants to ask you. In each question he gives you numbers l, r and k and you should tell him the number


题意:给出N个串,M个询问,对于每个询问L,R,K,给出串L到串R的所有串中串K作为子串出现了几次。

解法:根据正解重新写了一遍,将N个串插入AC自动机,再根据Fail指针重新构建Fail树,可知Fail树有性质父节点都是其子节点的最长的非本身后缀,且其为某串前缀,故而父节点都是子节点所在串的子串,有了这一性质,可以搞出Fail树的DFS序,然后变成了统计子树内,所代表串的编号在L,R内的所有节点的权值和,很明显可以离线树状数组搞,如果要在线处理询问,可以用主席树。

代码: (离线树状数组,500MS左右,比SA写法快了几倍...)

#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#include<iostream>#include<stdlib.h>#include<set>#include<map>#include<queue>#include<vector>#include<bitset>#pragma comment(linker, "/STACK:1024000000,1024000000")template <class T>bool scanff(T &ret){ //Faster Input    char c; int sgn; T bit=0.1;    if(c=getchar(),c==EOF) return 0;    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    if(c==' '||c=='\n'){ ret*=sgn; return 1; }    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;    ret*=sgn;    return 1;}#define inf 1073741823#define llinf 4611686018427387903LL#define PI acos(-1.0)#define lth (th<<1)#define rth (th<<1|1)#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)#define mem(x,val) memset(x,val,sizeof(x))#define mkp(a,b) make_pair(a,b)#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define pb(x) push_back(x)using namespace std;typedef long long ll;typedef pair<int,int> pii;#define NN 500500int tot,q[NN],nxt[NN][26],fail[NN],fa[NN];int ptx[NN],lnum,last[NN];struct edge{    int v,next;    edge(){}    edge(int v,int next){        this->v=v;        this->next=next;    }}ed[NN*2];void addedge(int x,int y){    ed[lnum]=edge(y,ptx[x]);    ptx[x]=lnum++;}void insert(int x,char *s){    int len=strlen(s);    int root=1;    rep(i,0,len-1){        int idx=s[i]-'a';        if(!nxt[root][idx]){            nxt[root][idx]=++tot;            fa[tot]=root;        }        root=nxt[root][idx];    }    last[x]=root;}void getfail(){    int head=0,tail=0;    q[tail++]=1;    while(head<tail){        int x=q[head++];        if(fail[x]){            addedge(x,fail[x]);            addedge(fail[x],x);        }        rep(i,0,25){            if(!nxt[x][i])nxt[x][i]=nxt[fail[x]][i];            else{                fail[nxt[x][i]]=nxt[fail[x]][i];                q[tail++]=nxt[x][i];            }        }    }}void init(){    tot=1;    rep(i,0,25)nxt[0][i]=1;    mem(ptx,-1);}int pos[NN],lx[NN],rx[NN],cot;void dfs(int x,int fa){    pos[++cot]=x;    lx[x]=cot;    gson(i,x){        int y=ed[i].v;        if(y==fa)continue;        dfs(y,x);    }    rx[x]=cot;}int ans[NN];struct node{    int l,r,idx;    node(){}    node(int l,int r,int idx){        this->l=l;        this->r=r;        this->idx=idx;    }};vector < node > q1[NN],q2[NN];int c[NN];#define lowbit(x) (x&(-x))void add(int x,int val){    for(int i=x;i<=tot;i+=lowbit(i))c[i]+=val;}int getsum(int x){    int sum=0;    while(x){        sum+=c[x];        x-=lowbit(x);    }    return sum;}int n,qn;char s[NN];int main(){    init();    scanff(n);    scanff(qn);    rep(i,1,n){        scanf("%s",s);        insert(i,s);    }    getfail();    dfs(1,0);    rep(i,1,qn){        int l,r,k;        scanff(l);        scanff(r);        scanff(k);        q1[l].pb(node(lx[last[k]],rx[last[k]],i));        q2[r].pb(node(lx[last[k]],rx[last[k]],i));    }    rep(i,1,n){        int x=last[i];        while(x)add(lx[x],1),x=fa[x];        rep(j,0,q1[i+1].size()-1)            ans[q1[i+1][j].idx]-=getsum(q1[i+1][j].r)-getsum(q1[i+1][j].l-1);    }    rep(i,1,n){        rep(j,0,q1[i].size()-1)            ans[q1[i][j].idx]+=getsum(q1[i][j].r)-getsum(q1[i][j].l-1);    }    mem(c,0);    drep(i,n,1){        int x=last[i];        while(x)add(lx[x],1),x=fa[x];        rep(j,0,q2[i-1].size()-1)            ans[q2[i-1][j].idx]-=getsum(q2[i-1][j].r)-getsum(q2[i-1][j].l-1);    }    rep(i,1,qn)        printf("%d\n",ans[i]);    return 0;}


0 0
原创粉丝点击