【WC2016模拟】打击目标

来源:互联网 发布:牛肉汤成本算法 编辑:程序博客网 时间:2024/06/05 17:44

Description

这里写图片描述

Input

这里写图片描述

Output
这里写图片描述

Sample Input

3 0
xyz xy x
1 2
2
1 3 xyz
2 3 zzzzxy

Sample Output

3
2

Data Constraint
这里写图片描述

题解

这一题在比赛的时候我已经想到了和题解基本一样的做法,然而因为不会树剖(雾,所以只打了50point,结果数据超级水,要不是开小了数组就AC了QvQ
下午赶紧学习了一下树剖,然后发现是一个超级简单的东西,就是维护出每一个点对应的重链的上面的顶点是什么,然后看哪边深就跳哪边就好了

那么这一题怎么做呢?

收先看到多串匹配条件反射的就想到了SA和AC自动机
看了一下发现就是一个AC自动机
某一个串经过的自动机中某一节点沿着fail能跳到的就是它的子串

那么我们不妨对自动机中的每一个点挂一个可持久化线段树,然后沿着fail边不断的更新就好了

询问的话因为树剖了一下所以只有log段,复杂度应该是两个log的

贴代码

打的不是很优美。。。

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fo1(i,b,a) for(i=b;i>=a;i--)#define max(x,y) ((x)>(y)?(x):(y))using namespace std;const int maxn=1e5+5;int tree[maxn*10][27],fail[maxn*10],h[maxn*10];int tr[maxn*50][3];int ff[maxn][18];int cc[maxn*10],de[maxn],dep[maxn*10];int fi[maxn],ne[maxn*2],dui[maxn*2],qc[maxn],siz[maxn];int fi1[maxn*3],ne1[maxn*5],dui1[maxn*5],qc1[maxn*3];int fa[maxn],dfn[maxn],top[maxn],go[maxn],root[maxn*10];bool bq;int i,j,k,l,m,n,x,y,z,o,ans,now,q,xz,zo,zz,cz,mx,xx,yy,p,xc;char s[maxn];void add(int x,int y){    if (fi[x]==0) fi[x]=++mx; else ne[qc[x]]=++mx;    dui[mx]=y; qc[x]=mx;}void add1(int x,int y){    if (fi1[x]==0) fi1[x]=++mx; else ne1[qc1[x]]=++mx;    dui1[mx]=y; qc1[x]=mx;}void ge_a(){    k=0;    fo(i,1,26) if (tree[0][i]) h[++k]=tree[0][i];    i=k; j=0;    while (i>j){        j++; x=h[j];        fo(k,1,26) if (tree[x][k]){            now=fail[x];            while (tree[now][k]==0 && now>0) now=fail[now];            if (tree[now][k]) now=tree[now][k];            fail[tree[x][k]]=now;            h[++i]=tree[x][k];        }    }}void ge_ff(){    fo(j,1,16)        fo(i,1,n) ff[i][j]=ff[ff[i][j-1]][j-1];}int lca(int x,int y){    if (de[x]<de[y]){        int z=x; x=y; y=z;    }    fo1(i,16,0) if (de[x]-(1<<i)>=de[y]) x=ff[x][i];    fo1(i,16,0) if (ff[x][i]!=ff[y][i]){        x=ff[x][i]; y=ff[y][i];    }    if (x!=y) x=ff[x][0];    return x;}void dfs(int x){    int i=fi[x]; siz[x]=1;     while (i){        de[dui[i]]=de[x]+1;        dfs(dui[i]);        siz[x]+=siz[dui[i]];        if (siz[dui[i]]>siz[go[x]]) go[x]=dui[i];        i=ne[i];    }}void dfss(int x){    dfn[x]=++now;    top[go[x]]=top[x];    if (go[x]) dfss(go[x]);    int i=fi[x];    while (i){        if (dui[i]==go[x]){            i=ne[i]; continue;        }        top[dui[i]]=dui[i];        dfss(dui[i]);        i=ne[i];    }}void maketree(int v,int s1,int s2,int l,int r){    tr[++p][0]=tr[v][0]; tr[p][1]=tr[v][1]; tr[p][2]=tr[v][2];    int q=p;    if (l==r){        tr[p][2]=s2; return;    }    int mid=(l+r)/2;    if (s1<=mid){        tr[p][0]=p+1;        maketree(tr[v][0],s1,s2,l,mid);    } else{        tr[p][1]=p+1;        maketree(tr[v][1],s1,s2,mid+1,r);    }    tr[q][2]=max(tr[tr[q][0]][2],tr[tr[q][1]][2]);}void wor(int x){    if (! root[fail[x]] && fail[x]) wor(fail[x]);    if (fi1[x]){        int pp=fi1[x];        root[x]=p+1;        maketree(root[fail[x]],dfn[dui1[pp]],dep[x],1,n); pp=ne1[pp];        while (pp){            int qq=p+1;            maketree(root[x],dfn[dui1[pp]],dep[x],1,n);            root[x]=qq;            pp=ne1[pp];        }    }        else root[x]=root[fail[x]];}void find(int v,int l,int r,int x,int y){    if (l==x && r==y) ans=max(ans,tr[v][2]); else{        int mid=(l+r)/2;        if (y<=mid) find(tr[v][0],l,mid,x,y); else        if (x>mid) find(tr[v][1],mid+1,r,x,y); else{            find(tr[v][0],l,mid,x,mid);            find(tr[v][1],mid+1,r,mid+1,y);        }    }}void tur(int q){    xx=x; yy=y;    while (top[xx]!=top[yy]){        if (de[top[xx]]<de[top[yy]]){            find(root[q],1,n,dfn[top[yy]],dfn[yy]);            yy=fa[top[yy]];        } else{            find(root[q],1,n,dfn[top[xx]],dfn[xx]);            xx=fa[top[xx]];        }    }    if (dfn[xx]>dfn[yy]){        z=xx; xx=yy; yy=z;    }    find(root[q],1,n,dfn[xx],dfn[yy]);}int main(){//  freopen("t2.in","r",stdin);//  freopen("t2.out","w",stdout);    scanf("%d%d",&n,&o);    fo(i,1,n){        scanf("%s",s+1); l=strlen(s+1);        now=0;        fo(j,1,l){            x=s[j]-96;            if (tree[now][x]) now=tree[now][x]; else{                tree[now][x]=zo+1; dep[++zo]=dep[now]+1;                 now=tree[now][x];            }        }        add1(now,i);    }    ge_a(); mx=0;    fo(i,2,n){        scanf("%d",&ff[i][0]); fa[i]=ff[i][0];        add(ff[i][0],i);    }    ge_ff();    now=0;    dfs(1); top[1]=1;     dfss(1); p=0;    fo(i,1,zo)        if (! root[i]) wor(i);    scanf("%d",&q); ans=0;    fo(xz,1,q){        scanf("%d%d",&x,&y);        if (o){            x^=ans; y^=ans;        } xx=x; yy=y;        z=lca(x,y);        now=0; scanf("%s",s+1); l=strlen(s+1); ans=0;        fo(i,1,l){            xc=s[i]-96;            while (now>0 && tree[now][xc]==0) now=fail[now];            if (tree[now][xc]) now=tree[now][xc];            tur(now);        }        printf("%d\n",ans);    }    return 0;}
阅读全文
'); })();
1 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 灭蟑螂药物 医院灭蟑螂 超市灭蟑螂 驱杀蟑螂 蟑螂多 抓蟑螂 灭 蟑螂 杀杀蟑螂 专杀蟑螂 冬季灭蟑螂 蟑螂的产生 蟑螂专家 春季灭蟑螂 嗜血蟑螂 蟑螂是什么 家庭灭蟑螂 家庭 灭蟑螂 蟑螂爬到床上还能睡吗 樟脑丸能防蟑螂吗 房间有蟑螂睡觉危险吗 蟑螂咬人后症状图片 怎么预防蟑螂爬床上 灭蟑螂有效方法 用脚踩死蟑螂后怎么补救 末日蟑螂txt下载 如何消除蟑螂 蟑螂怎么来的 如何驱赶蟑螂 怎么样消灭蟑螂 大蟑螂怎么消灭 如何杀死蟑螂 怎么清除蟑螂 怎么消除蟑螂 蟑螂怎么清除 蟑螂的危害及清除办法 怎么灭绝蟑螂 怎么去除蟑螂 如何去蟑螂妙招 怎么除掉蟑螂 怎么杀死蟑螂 怎样去除蟑螂