如何判断一个字符串无法作为字典序最小?
1.前缀出现
2.大小矛盾(出现环)
解决1.用字典树来存,先存再输出,记录单词结束位置,输出时判断前面的字母是否有为其他单词的结束
解决2.用拓扑排序判断环
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 10;
struct node{
char c;
bool end;
node* right;
node* nex;
}p[MAXN];
int ptop = 1;
bool able[30001];
node* find(char c,node* pp)
{
if(pp -> nex == NULL)
{
pp -> nex = &p[ptop];
p[ptop++].c = c;
return pp -> nex;
}
pp = pp -> nex;
node* ppp;
while(pp != NULL)
{
if(pp -> c == c)
return pp;
ppp = pp;
pp = pp -> right;
}
ppp -> right = &p[ptop];
p[ptop++].c = c;
return ppp -> right;
}
void add(string str)
{
int end = str.size();
node* pp = &p[0];
for(int i = 0;i < end;i++)
{
pp = find(str[i],pp);
}
pp -> end = true;
}
int main()
{
int n;cin >> n;
string st[30001];
for(int i = 1;i <= n;i++)
{
string str;cin >> st[i];
add(st[i]);
}
int sum = 0;
for(int i = 1;i <= n;i++)
{
int end = st[i].size();
node* pp,*ppp = p[0].nex;
vector<int> a[26];
int num[26] = {0};
bool flag = true;
for(int j = 0;j < end;j++)
{
pp = ppp;
while(pp != NULL)
{
if(pp -> c != st[i][j])
{
a[st[i][j] - 'a'].push_back(pp -> c - 'a');
num[pp -> c - 'a']++;
}
else
{
if(j != end - 1 && pp -> end == true)
flag = false;
ppp = pp -> nex;
}
pp = pp -> right;
}
}
queue<int> qu;
for(int i = 0;i < 26;i++)
{
if(num[i] == 0)
qu.push(i);
}
while(!qu.empty())
{
int x = qu.front();qu.pop();
int end = a[x].size();
for(int i = 0;i < end;i++)
{
num[a[x][i]]--;
if(num[a[x][i]] == 0)
qu.push(a[x][i]);
}
}
for(int i = 0;i < 26;i++)
{
if(num[i] != 0)
flag = false;
}
if(flag)
able[i] = 1,sum++;
}
cout << sum << endl;
for(int i = 1;i <= n;i++)
{
if(able[i])
cout << st[i] << endl;
}
}