牛客网 练习赛11 B题 假的字符串 tire+topsort判环

题目链接: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("");
    }

}

你可能感兴趣的:(----字典树,dfs)