链接:https://www.nowcoder.com/acm/contest/59/B
来源:牛客网题目描述
给定n个字符串,互不相等,你可以任意指定字符之间的大小关系(即重定义字典序),求有多少个串可能成为字典序最小的串,并输出它们
输入描述:
第一行一个数表示n 之后n行每行一个字符串表示给定的字符串
输出描述:
第一行输出一个数x表示可行的字符串个数 之后输出x行,每行输出一个可行的字符串 输出的顺序和输入的顺序一致
示例1
输入
6 mcfx ak ioi wen l a
输出
5 mcfx ioi wen l a 题解:首先建立字典树,然后对于每个字符串判定是否有冲突,如果chara < charb,则a向b连一条单向边。#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; using namespace std; #define SZ(X) ((int)X.size()) #define mp make_pair #define pb push_back #define RALL(X) X.rbegin(),X.rend() #define ALL(X) X.begin(),X.end() using ll = long long ; using ld = long double ; const int N = 30007, M = 3E6 + 7; int tot; string s[N]; struct T { int tree[M][26]; int val[M]; int in[26]; bool vis[26]; int cnt; vector<int>G[26]; void insert(string& p) { int now = 0; for(int i = 0;i < SZ(p);i ++) { int key = p[i] - 'a'; if(tree[now][key] == 0) { tree[now][key] = ++ tot; } now = tree[now][key]; } val[now] = 1; } bool check(string& p) { for(int i = 0;i < 26;i ++) G[i].clear(); cnt = 0; int now = 0; memset(in, 0, sizeof(in)); memset(vis, 0, sizeof(vis)); for(int i = 0;i < SZ(p);i ++) { int key = p[i] - 'a'; vis[key] = 1; for(int k = 0;k < 26;k ++) { if(key != k && tree[now][k]) { G[key].pb(k); in[k] ++; vis[k] = 1; } } if(val[now]) return false; now = tree[now][key]; } queue<int> que; for(int i = 0;i < 26;i ++) cnt += vis[i]; int ck = 0; for(int i = 0;i < 26;i ++) { if(!in[i] && vis[i]) { que.push(i); ++ ck; } } while(!que.empty()) { int u = que.front(); que.pop(); for(int i = 0;i < SZ(G[u]);i ++) { int v = G[u][i]; -- in[v]; if(in[v] == 0) { ++ ck ; que.push(v); } } } return ck == cnt; } }AC; int main() { std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); cout << fixed; int n; cin >> n; for(int i = 0;i < n;i ++) { cin >> s[i]; AC.insert(s[i]); } vector<int>ANS; for(int i = 0;i < n;i ++) { if(AC.check(s[i])) { ANS.pb(i); } } cout << SZ(ANS) << "\n"; for(int i = 0;i < SZ(ANS);i ++) { cout << s[ANS[i]] << "\n"; } return 0; }