rt,样例过了,AC on #1 #5 #8,下载#2后自己跑了一遍没有输出,怀疑是数组开小了,但是 tree[1e7+5][27]又超时了
注:#2 数据大小30000个字符串,而且输出也是30000个
#include <bits/stdc++.h>
#define m(i,a,b) for (int i=a;i<=b;--i)
#define f(i,a,b) for (int i=a;i<=b;++i)
#define ll long long
#define Shion cout <<"Shion is too poor to print that."<<'\n'
const signed N=300005;
const signed Miku=0x3f3f3f3f;
using namespace std;
int n,tot;
int tree[300005][27];
int ext[30005];
string s[30005];
vector <int> node[27];// 邻接表 1-26字母的树 记录规则 有环证明该字符串不能成为字典序第一
int in[27];// 入度
queue <int> ans;
// DebugSwitch(1);
void build(string s){
int now=0,c=0;
int len=s.length();
f(i,0,len-1){
c=s[i]^96;
if(!tree[now][c])
tree[now][c]=++tot;
now=tree[now][c];
}
ext[now]++;
// DebugOut<<"ext "<<now<<'\n';
}
bool check(string s){
memset(node,0,sizeof(node));
memset(in,0,sizeof(in));
int now=0;
int c=0;
int len=s.length();
f(i,0,len-1){
c=s[i]^96;
if(ext[now]&&i<len-1){
// 这意味着,有一个字符串是另一个的前缀
// 必定失败
// DebugOut<<"Failed at "<<s[i]<<'\n';
return 0;
}
else{
f(j,1,26){
if(tree[now][j]&&j!=c){
// 这意味着,有两个前缀相同的字符串
// 此时添加规则使得本字符串字符优先于另一个
// 即 j>c 转为 j->c
node[j].push_back(c);
in[c]++;
}
}
}
now=tree[now][c];
}
f(i,1,26){
if(node[i].size()){
f(j,0,node[i].size()-1){
// DebugOut<<(char)(i+96)<<'>'<<(char)(node[i][j]+96)<<'\n';
}
}
}
// 检查node是否有环
vector<int> L;
queue<int> S;
f(i,1,26)
if(!in[i])// 入度为0的点入队
S.push(i);
while (!S.empty()) {
int u = S.front();
S.pop();
L.push_back(u);
for (auto v : node[u]) {
if (--in[v] == 0) {
S.push(v);
}
}
}
if (L.size() == 26) {
// for (auto i : L) // DebugOut << i << ' ';
return 1;// 没有环
}
return 0;// 有环
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0);
// init
cin>>n;
f(i,1,n){
cin>>s[i];
build(s[i]);
}
// check
f(i,1,n){
// DebugOut<<"checking "<<s[i]<<"..."<<'\n';
if(check(s[i])){
ans.push(i);
// DebugOut<<"OK"<<'\n';
}
}
cout<<ans.size()<<'\n';
while(!ans.empty()){
cout<<s[ans.front()]<<'\n';
ans.pop();
}
return 0;
Shion;
}