3439: Kpm的MC密码 trie+主席树

来源:互联网 发布:godaddy购买域名教程 编辑:程序博客网 时间:2024/04/29 06:50

一开始写的fail树,然后沿着fail指针反向dfs。结果TLE啦。
看了一下题解,是把后缀相同转化为前缀相同,然后在trie树上有相同前缀的肯定在同一棵子树中,按dfs序建主席树就行啦。
其实在fail树上建主席树也是可以的。。一开始傻逼没有想到。。懒得改了。。
注意有相同的子串!

fail树暴力

#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<cstring>#define N 100005using namespace std;int n,cnt,top;int a[N][26],p[N],pos[N],q[N],stack[N];bool flag[N];char s[N];vector<int> b[N];vector<int> id[N];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x){    scanf("%s",s);    int c,now=1,len=strlen(s);    for (int i=0;i<len;i++)    {        c=s[i]-'a';        if (a[now][c]) now=a[now][c];        else now=a[now][c]=++cnt;    }    id[now].push_back(x); pos[x]=now; flag[now]=1;}inline void build_fail(){    int t=0,w=1,now;    q[1]=1; p[1]=0;    while (t<w)    {        now=q[++t];        for (int i=0;i<26;i++)            if (a[now][i])            {                int k=p[now];                while (!a[k][i]) k=p[k];                p[a[now][i]]=a[k][i];                if (a[k][i]!=1) b[a[k][i]].push_back(a[now][i]);                q[++w]=a[now][i];            }    }}void dfs(int x){    if (flag[x])         for (int i=0;i<id[x].size();i++) stack[++top]=id[x][i];    for (int i=0;i<b[x].size();i++) dfs(b[x][i]);}int main(){//  freopen("password.in","r",stdin);//  freopen("password.out","w",stdout);    n=read(); cnt=1;    for (int i=0;i<26;i++) a[0][i]=1;    for (int i=1;i<=n;i++) insert(i);    build_fail();    for (int i=1;i<=n;i++)     {        top=0;        dfs(pos[i]);        sort(stack+1,stack+top+1);        int k=read();        if (k>top) puts("-1");        else printf("%d\n",stack[k]);    }    return 0;}
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<cstring>#define N 100005using namespace std;int n,cnt,dfn,size;int a[N][26];int in[N],out[N],root[N],pos[N],p[N];char s[N];int ls[5000005],rs[5000005],sum[5000005];vector<int> id[N];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x){    scanf("%s",s);    int c,now=1,len=strlen(s);    for (int i=len-1;~i;i--)    {        c=s[i]-'a';        if (a[now][c]) now=a[now][c];        else now=a[now][c]=++cnt;    }    id[now].push_back(x); p[x]=now; }void dfs(int x){    in[x]=++dfn; pos[dfn]=x;    for (int i=0;i<26;i++)        if (a[x][i]) dfs(a[x][i]);    out[x]=dfn;}void update(int l,int r,int x,int &y,int val){    y=++size;    ls[y]=ls[x]; rs[y]=rs[x]; sum[y]=sum[x]+1;    if (l==r) return;    int mid=l+r>>1;    if (val<=mid) update(l,mid,ls[x],ls[y],val);    else update(mid+1,r,rs[x],rs[y],val);}int query(int x,int y,int k){    if (k>sum[y]-sum[x]) return -1;    int l=1,r=n;    while (l!=r)    {        int mid=l+r>>1;        int tmp=sum[ls[y]]-sum[ls[x]];        if (tmp>=k) r=mid,x=ls[x],y=ls[y];        else l=mid+1,k-=tmp,x=rs[x],y=rs[y];    }    return l;}int main(){//  freopen("password.in","r",stdin);//  freopen("password.out","w",stdout);    n=read(); cnt=1;    for (int i=0;i<26;i++) a[0][i]=1;    for (int i=1;i<=n;i++) insert(i);    dfs(1);    for (int i=1;i<=cnt;i++)        if (id[pos[i]].size()!=0)         {            update(1,n,root[i-1],root[i],id[pos[i]][0]);            for (int j=1;j<id[pos[i]].size();j++)                 update(1,n,root[i],root[i],id[pos[i]][j]);        }        else root[i]=root[i-1];    for (int i=1;i<=n;i++)    {        int k=read();        printf("%d\n",query(root[in[p[i]]-1],root[out[p[i]]],k));    }    return 0;}
0 0
原创粉丝点击