dtoj1348. 第一字符串(first)

Bessie 最近在玩字符串。她发现通过改变字母的顺序可以使一些字符串排在其他所有的字符串之前(按字典序从小到大排序)。

比如说,Bessie 找到了对于字符串”omm”,”moo”,”mom”,和”ommnom”,她可以用标准的字母表把”mom” 排在最前面, 也可以用字母表”abcdefghijklonmpqrstuvwxyz”把”omm”排在最前面。但是,Bessie 不能找出一个方案使”moo”或”ommnom”排在最前面。

请你帮助Bessie 找出哪些字符串可以通过改变字母表来让它们排在最前面。要计算字符串X 是否字典序比字符串Y 小,要找到两个字符串最先出现的不同字符的位置,j。如果没有这样的位置存在,那么如果X 的长度比Y 短,则X 字典序小于Y。否则,如果X[j]在字母表中比Y[j]早出现,那么X 字典序小于Y。


Sol

考虑建trie 在trie上dfs然后维护各个字母的大小关系,遇到关键点check下就没了

效率 n*26*26

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#define maxn 300005
using namespace std;
int n,tr[maxn][26],cnt,id[maxn],can[maxn];
int s[26][26],f[26],in[26],sum;
char ch[maxn];
string a[maxn];
void ins(int x){
    int k=0,l=strlen(ch);
    for(int i=0;i<l;i++){
        if(!tr[k][ch[i]-'a'])tr[k][ch[i]-'a']=++cnt;
        k=tr[k][ch[i]-'a'];
    }
    id[k]=x;
}
bool Dfs(int k,int co){
    if(f[k]==co)return !in[k];
    f[k]=co;in[k]=1;bool T=1;
    for(int i=0;i<26;i++){
        if(i^k&&s[k][i])T&=Dfs(i,co);
    }
    in[k]=0;
    return T;
}
void check(int x){
    bool T=1;
    for(int i=0;i<26;i++){
        if(f[i]!=x)T&=Dfs(i,x);
        if(!T)return;
    }
    can[x]=1;sum++;
}
void dfs(int k){
    int tmp[26],t=0;
    if(id[k]){check(id[k]);return;}
    for(int i=0;i<26;i++){
        if(tr[k][i])tmp[++t]=i;
    }
    for(int i=0;i<26;i++){
        if(tr[k][i]){
            for(int j=1;j<=t;j++)s[i][tmp[j]]++;
            dfs(tr[k][i]);
            for(int j=1;j<=t;j++)s[i][tmp[j]]--;
        }
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf(" %s",ch);ins(i);
        a[i]=(string)ch;
    }
    dfs(0);
    cout<<sum<<endl;
    for(int i=1;i<=n;i++)if(can[i])cout<<a[i]<<endl;
    return 0;
}
View Code

 

posted @ 2020-02-08 19:57  liankewei123456  阅读(167)  评论(0编辑  收藏  举报