ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P3065 [USACO12DEC]First! G

2021-08-02 22:33:54  阅读:171  来源: 互联网

标签:USACO12DEC ... P3065 int ll register Trie 字符 First


Trie树 上拓扑。

为什么这道题目要建立 Trie树 呢...因为对于两个字符串,比较他们的字典序大小无非就是比较他们第一个相当的字符是什么,也就是说,如果这两个字符串在第 \(k\) 位开始不一样,那么他们也会在 \(k\) 对应的节点分别走向 \(k\) 不同的儿子。

暴力的思路无非就是暴力枚举、暴力判断吧...枚举应该是不能优化了(?),而判断可以借助 Trie树 来优化判断呀。存在大小关系...是不是可以将大小关系变为一个有向图呢?如果这个字符不可能是解的话,一定存在一组字符 \(u\) 和 \(v\) 使得 \(u\) 既要优先于 \(v\) ,\(v\) 也要优先与 \(u\)...

对于一个字符串,我们先假定这个字符串是字典序最小的,那么是不是就可以确定每个字符之间的大小关系呢...所以我们可以对于这个钦定的字符串 \(s\) 的每一位对应的 Trie树 上的节点 \(id\) ,遍历 \(id\) 的每一个子结点(因为 Trie树 上并没有记录每个点存在的子结点有几个,所以只能 \(0\) 至 \(25\) 来枚举),如果这个子结点有不同于 \(s\) 这一位的字符 \(j\) ,并且 \(id\) 存在 \(j\) 这个儿子,并且 \(tmp\) 暂时没有与 \(j\) 确定大小关系,那么很明显 \(tmp\) 是要优先于 \(j\) 的 ,因此 \(tmp\) 向 \(j\) 连上一条边。

很显然,如果存在一个可以的排列的话,这个有向图一定是一个 DAG !每个字符都存在一个固定字符排在它的前一位...

于是通过这个循环,我们确定了优先级...

ll id=0,len=x.length();
    memset(e,0,sizeof(e));
    memset(in,0,sizeof(in));
    for(register int i=0;i<len;++i){
        if(ed[id])  return 0;
        ll tmp=x[i]-'a';
        for(register int j=0;j<26;++j)
            if(tmp!=j&&trie[id].ch[j]&&!e[tmp][j]){
                e[tmp][j]=1;
                ++in[j];
            }
        id=trie[id].ch[tmp];
    }

如何判断是不是 DAG 呢...拓扑排序啊。

如果一个点始终不能将入度变为 \(0\) ,说明这个有向图是存在环的!这样就很好判断了呀~如果存在环说明一定存在一个 \(u\) 和一个 \(v\) 使得 \(u\) 要优先于 \(v\) 而 \(v\) 也要优先于 \(u\)!

至此,这道题目就做完了呀...

拓扑排序:

queue<ll>q;
    while(!q.empty())    q.pop();
    for(register int i=0;i<26;++i)  
        if(!in[i])  
            q.push(i);
    while(!q.empty()){
        ll u=q.front();q.pop();
        for(register int i=0;i<26;++i)
            if(e[u][i]){
                --in[i];
                if(!in[i])
                    q.push(i);
            }
    }

判断是否为 DAG:

for(register int i=0;i<26;++i)
        if(in[i])
            return 0;
    return 1;

完整程序:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,cnt,node,ed[400001],in[30],ans,e[30][30],ok[30001];
string s[30001],c;
struct Node{
    ll fail=0,num=0,ch[25];
}trie[400001];

inline ll read(){
    ll x=0,f=0;char c=getchar();
    while(!isdigit(c))  f|=c=='-',c=getchar();
    while(isdigit(c))   x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
}

inline void build(ll x){
    ll id=0,len=s[x].length();
    for(register int i=0;i<len;++i){
        ll tmp=s[x][i]-'a';
        if(!trie[id].ch[tmp])
            trie[id].ch[tmp]=++cnt;
        id=trie[id].ch[tmp];
    }
    ed[id]=1;
}

inline int find(string x){
    ll id=0,len=x.length();
    memset(e,0,sizeof(e));
    memset(in,0,sizeof(in));
    for(register int i=0;i<len;++i){
        if(ed[id])  return 0;
        ll tmp=x[i]-'a';
        for(register int j=0;j<26;++j)
            if(tmp!=j&&trie[id].ch[j]&&!e[tmp][j]){
                e[tmp][j]=1;
                ++in[j];
            }
        id=trie[id].ch[tmp];
    }
    queue<ll>q;
    while(!q.empty())    q.pop();
    for(register int i=0;i<26;++i)  
        if(!in[i])  
            q.push(i);
    while(!q.empty()){
        ll u=q.front();q.pop();
        for(register int i=0;i<26;++i)
            if(e[u][i]){
                --in[i];
                if(!in[i])
                    q.push(i);
            }
    }
    for(register int i=0;i<26;++i)
        if(in[i])
            return 0;
    return 1;
}

int main(){
    n=read();
    for(register int i=1;i<=n;++i){
        cin>>s[i];
        build(i);
    }
    for(register int i=1;i<=n;++i)
        if(find(s[i])){
            ++ans;
            ok[i]=1;
        }
    printf("%lld\n",ans);
    for(register int i=1;i<=n;++i)
        if(ok[i])
            cout<<s[i]<<endl;
    return 0;
}

标签:USACO12DEC,...,P3065,int,ll,register,Trie,字符,First
来源: https://www.cnblogs.com/sissi/p/15091998.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有