题目链接:https://www.nowcoder.com/acm/contest/59#submit/{%22problemIdFilter%22%3A15049%2C%22statusTypeFilter%22%3A%225%22%2C%22page%22%3A1}
链接: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
备注:
对于100%的数据,
n <= 30000 , 字符串总长<= 300000
字符集为小写字符
解析:
先把字符串全部插入到字典树中,这里要用数组表示的字典树,不然会MLE
1.如果存在字符串A是字符串B的前缀,那么字符串B肯定不可能是最小的情况
2.否则的话,我们判断一个字符串是不是可能最小,我们只要使该字符串的字母是同阶下最小的就行了。譬如说mcfc mcfx mcfm mm xx 要使mcfc最小,那么首先他的第一个字母是要在所有第一个字母中最小的(m
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1000005;
typedef long long ll;
char str[maxn];
vector<string> dir;
vector<int> ans;
bool vis[30];
set<int> G[30];
bool dfs(int x,int y){//暴力dfs判环, 复杂度可以是挺大的....如果构造了一些数据的话.
if(x==y&&vis[y]) return true;
if(vis[x]) return false;
vis[x]=true;
for(set<int>::iterator it=G[x].begin();it!=G[x].end();it++){
int v = *it;
if(dfs(v,y)) return true;
}
return false;
}
struct Trie {
int ch[maxn][30];
int val[maxn];
int sz;
Trie() {sz = 1; memset(ch[0], 0, sizeof(ch[0]));}
void clear(){sz = 1;memset(ch[0], 0, sizeof(ch[0]));}
int idx(char c) { return c - 'a'; }
void insert(char *s, int v) {
int u = 0;
int n = strlen(s);
for (int i = 0; i < n; i++) {
int c = idx(s[i]);
if (!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
// val[u]=v;
u = ch[u][c];
}
val[u] = v;
}
bool ok(string& s,int v) {
int u = 0;
int len=s.size();
for(int i=0;i<26;i++) G[i].clear();
for (int i = 0; i < len; i++) {
int c = idx(s[i]);
if (!ch[u][c]) break;
for(int j=0;j<26;j++) if(ch[u][j]&&j!=c) {
G[c].insert(j);
}
u = ch[u][c];
if(val[u]&&val[u]!=v) return false;
}
for(int i=0;i<26;i++) {
memset(vis,false,sizeof(vis));
if(dfs(i,i)) return false;
}
return true;
}
};
Trie tree;
int main() {
int n;
scanf("%d",&n);
tree.clear();
for (int i = 1; i <= n; i++) {
scanf("%s", str);
string s(str);
tree.insert(str, i);
dir.push_back(s);
}
for(int i=0;iif(tree.ok(dir[i],i+1)){
ans.push_back(i);
}
}
printf("%d\n",ans.size());
for(int i=0;icout<'\n';
}
return 0;
}
hsh的,用topsort,这样的话O(n);
#include
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 30005;
const int M = 300005;
const int ALL = (1 << 26) - 1;
struct Trie
{
int nxt[26], cnt;
void init()
{
for (int i = 0; i < 26; ++i)
nxt[i] = 0;
cnt = 0;
}
} L[M];
int sz;
char s[M];
int st[N], len[N], pos[N];
int E[30][30], deg[30], A[30][30];//A用来去重边.
void clr()
{
for(register int i = 0; i < 30; ++i)
{
deg[i] = 0;
for (register int j = 0; j < 30; ++j)
E[i][j] = A[i][j] = 0;
}
}
void init()
{
sz = 0;
L[sz++].init();
}
inline int newnode()
{
L[sz].init();
return sz++;
}
inline int check(char s[], int len)
{
int u = 0;
for (int i = 0; i < len; ++i)
{
int v = s[i] - 'a';
if(L[u].cnt)
return false;
for (register int j = 0; j < 26; ++j)
{
if(v != j && L[u].nxt[j] && !A[v][j])
{
A[v][j] = 1;
E[v][++E[v][0]] = j;
++deg[j];
}
}
u = L[u].nxt[v];
}
return true;
}
inline int topsort()
{
queue<int>Q;
int state = 0;
for (int i = 0; i < 26; ++i)
{
if(!deg[i])
Q.push(i), state |= (1 << i);
}
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for (register int i = 1; i <= E[u][0]; ++i)
{
int v = E[u][i];
if(--deg[v] == 0)
{
Q.push(v);
state |= (1 << v);
}
}
}
return state == ALL;
}
inline void ins(char s[], int len)
{
int u = 0;
for (int i = 0; i < len; ++i)
{
int v = s[i] - 'a';
if(!L[u].nxt[v])
L[u].nxt[v] = newnode();
u = L[u].nxt[v];
}
L[u].cnt = 1;
}
int main(void)
{
register int n, i, j, ed;
scanf("%d", &n);
init();
for (i = 1; i <= n; ++i)
{
st[i] = st[i - 1] + len[i - 1];
scanf("%s", s + st[i]);
len[i] = strlen(s + st[i]);
ins(s + st[i], len[i]);
}
for (i = 1; i <= n; ++i)
{
clr();
if(check(s + st[i], len[i]) && topsort())
{
pos[++pos[0]] = i;
}
}
printf("%d\n", pos[0]);
for (i = 1; i <= pos[0]; ++i)
{
int x = pos[i];
for (ed = st[x] + len[x], j = st[x]; j < ed; ++j)
putchar(s[j]);
puts("");
}
return 0;
}
抄着kalids的代码的:
#include
using namespace std;
#define LL long long
#define N 300010
#define inf 0x3f3f3f3f
#define pb push_back
#define fi first
#define se second
#define mod 9999973
#define md ((l+r)>>1)
#define ls (i<<1)
#define rs (i<<1|1)
const int ALL=(1<<26)-1;
int sz,n;
int A[30][30],E[30][30],st[N],deg[30],pos[N],len[N];
char s[N];
struct Tire{
int nxt[26],cnt;
void init(){
for(int i=0;i<26;++i)
nxt[i]=0;
cnt=0;
}
}L[N];
inline int newnode(){
L[sz].init();
return sz++;
}
void insert(char s[],int len){
int u=0;
for(int i=0;iint v=s[i]-'a';
if(!L[u].nxt[v]){
L[u].nxt[v]=newnode();
}
u=L[u].nxt[v];
}
L[u].cnt=1;
//printf("L[%d].cnt=1",u);
}
void init(){
sz=0;
L[sz++].init();
}
inline bool topsort(){
int state=0;
queue<int>Q;
for(int i=0;i<26;++i){
if(!deg[i])state|=(1<while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=1;i<=E[u][0];++i){
int v=E[u][i];
if(--deg[v]==0){
Q.push(v);
state|=(1<return state==ALL;
}
bool check(char s[],int len){
int u=0;
for(int i=0;iint v=s[i]-'a';
if(L[u].cnt)return false;
for(int j=0;j<26;++j){
if(v!=j&&L[u].nxt[j]&&!A[v][j]){
A[v][j]=1;
E[v][++E[v][0]]=j;
++deg[j];
}
}
u=L[u].nxt[v];
}
return true;
}
inline void clr(){
for(int i=0;i<30;++i){
deg[i]=0;
for(int j=0;j<30;++j){
A[i][j]=E[i][j]=0;
}
}
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%d",&n);
init();
for(int i=1;i<=n;++i){
st[i]=st[i-1]+len[i-1];
scanf("%s",s+st[i]);
len[i]=strlen(s+st[i]);
//printf("i:%d %s\n",i,s+st[i]);
insert(s+st[i],len[i]);
}
//for(int i=1;i<=n;++i){
//printf("st[i]: %d len[i] : %d\n",st[i],len[i]);
//}
//printf("%d\n", sz);
for(int i=1;i<=n;++i){
clr();
int t1=check(s+st[i],len[i]);
int t2=topsort();
//cout<
if(t1&&t2){
pos[++pos[0]]=i;
//printf("OK:i = %d\n",i);
}
}
printf("%d\n",pos[0]);
for(int i=1;i<=pos[0];++i){
int x=pos[i];
for(int ed=st[x]+len[x],start=st[x];startputchar (s[start]);
}puts("");
}
}