简要题意
给出 \(n\) 个字符串 \(s_i\)。如果我们称 \(s_i\) 是美好的,当且仅当至少有一种方案规定 \(\texttt{a-z}\) 的大小关系,使得 \(s_i\) 字典序最小。输出有多少个字符串是美好的,并输出美好的字符串。
\(1 \leq n \leq 3\times10^4,1 \leq \sum_{i}|s_i| \leq 3 \times 10^5\),\(s_i\) 中仅包含小写英文字母。
思路
这道题的做法比较经典。
我们将 \(s_i\) 建出 Trie 树,那么如果一个字符串是美好的,我们要让 Trie 树上每一层的其他字符都比这个字符串在这一层的字符小。然后就可以了。
但是会出现我们无法找到这样的方案的情况。有这两种:
- 存在另一个字符串 \(t\) 是这个字符串 \(s\) 的前缀,这样肯定没有方案。因为无论如何都满足 \(t<s\)。
- 出现矛盾。例如,我们在前面认为 \(x<y\),后面又认为 \(y<x\)。这样就出现了矛盾,无解。
第一种情况判断比较简单。我们给字符串结尾打上标记,遍历时看看有没有标记即可。注意不要把自己的标记算上了。
第二种情况,我们可以连边 \((x,y)\)。然后就是判断一个有向图有没有环,Tarjan 求强连通分量解决即可。
时间复杂度 \(O(|S|+26n)\)。
代码
#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 300005;
int trie[N][26],stop[N],tot;
void insert(const string &x){
int cur=0;
for(char i : x){
if(!trie[cur][i-'a']) trie[cur][i-'a']=(++tot);
cur=trie[cur][i-'a'];
}
stop[cur]++;
}
bool g[30][30];
int dfn[30],low[30],dfncnt,ecc;
bool vis[30];
stack<int> sta;
void tarjan(int u){
dfn[u]=low[u]=(++dfncnt);vis[u]=1;
sta.push(u);
for(int v=0;v<26;v++){
if(!g[u][v]) continue;
if(!dfn[v]){
tarjan(v);low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
ecc++;
while(sta.top()!=u){
vis[sta.top()]=0;sta.pop();
}
sta.pop();vis[u]=0;
}
}
void clear(){
memset(g,0,sizeof(g));
memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));dfncnt=ecc=0;
while(!sta.empty()) sta.pop();
}
bool solve(const string &x){
clear();
int cur=0;
for(int i=0;i<x.size();i++){
if(stop[cur]) return false;
for(int j=0;j<26;j++){
if(trie[cur][j]&&x[i]!=(j+'a')) g[x[i]-'a'][j]=1;
}
cur=trie[cur][x[i]-'a'];
}
for(int i=0;i<26;i++){
if(!dfn[i]) tarjan(i);
}
return ecc==26;
}
string s[N];
vector<string> ret;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];insert(s[i]);
}
for(int i=1;i<=n;i++){
if(solve(s[i])) ret.push_back(s[i]);
}
cout<<ret.size()<<'\n';
for(string s : ret) cout<<s<<'\n';
return 0;
}
标签:USACO12DEC,cur,P3065,int,30,leq,trie,字符串,First
From: https://www.cnblogs.com/zheyuanxie/p/p3065.html