一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;
}