BZOJ 3012/Luogu 3065 [Usaco2012 Dec]First!

来源:互联网 发布:担保行业 知乎 编辑:程序博客网 时间:2024/05/21 06:38

一A啊 开心O(∩_∩)O~~

奥爷爷劲啊 Orzzzzzzzzzz

如果一个字符串想要是字典序最小 首先没有别的串是他的前缀

然后 对于有共同前缀的 其他的下一个字母的优先级一定要比此串下一个字母后

上面的过程就用trie树来搞定√

所以连一条边拓扑排序一下 如果全部排完那就可以咯

#include<queue>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#define me(a,x) memset(a,x,sizeof a)using namespace std;const int inf=1e9,M=300004,N=30005;inline int read(){    int x=0,f=1; char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}    return x*f;}struct node{int c[27],x;}t[M];bool mp[27][27],v[27]; int in[27],out[27];queue<int>Q;bool go(){    int u=0,s=0,i;    for(i=0;i<26;i++)    {        if(in[i] || out[i])u++;        if(!in[i] && out[i])Q.push(i),v[i]=1;        else v[i]=0;    }    while(!Q.empty())    {        int x=Q.front(); s++; Q.pop();        for(i=0;i<26;i++)          if(mp[x][i])          {              in[i]--; if(!in[i] && !v[i])Q.push(i);          }    }    if(s==u)return 1;    return 0;}char s[M],c[M];int st[N],tot,q[N];int main(){    int i,j,l,n=read(),now,x,y;    now=tot=0;    for(i=1;i<=n;i++)    {        scanf("%s",c);        l=strlen(c); st[i]=now; x=0;        for(j=0;j<l;j++)        {            s[now++]=c[j],y=c[j]-'a';            if(!t[x].c[y])t[x].c[y]=++tot;            x=t[x].c[y];        }        t[x].x=i;    }    int ans=0,k; st[n+1]=now;    for(i=1;i<=n;i++)    {        me(mp,0); me(in,0); me(out,0); x=0;        bool bk=0;        for(j=st[i];j<st[i+1];j++)        {            int y=s[j]-'a';            if(t[x].x){bk=1; break;}            for(k=0;k<26;k++)             if(t[x].c[k]&&k!=y&&!mp[y][k])                 mp[y][k]=1,in[k]++,out[y]++;            x=t[x].c[y];        }        if(bk)continue;        if(go())q[++ans]=i;    }    printf("%d\n",ans);    for(i=1;i<=ans;i++)    {        for(j=st[q[i]];j<st[q[i]+1];j++)printf("%c",s[j]);        printf("\n");    }    return 0;}


1 0
原创粉丝点击