首页 > 其他分享 >P3065 [USACO12DEC]First! G

P3065 [USACO12DEC]First! G

时间:2023-02-11 22:00:27浏览次数:34  
标签:USACO12DEC cur P3065 int 30 leq trie 字符串 First

简要题意

给出 \(n\) 个字符串 \(s_i\)。如果我们称 \(s_i\) 是美好的,当且仅当至少有一种方案规定 \(\texttt{a-z}\) 的大小关系,使得 \(s_i\) 字典序最小。输出有多少个字符串是美好的,并输出美好的字符串。

\(1 \leq n \leq 3\times10^4,1 \leq \sum_{i}|s_i| \leq 3 \times 10^5\),\(s_i\) 中仅包含小写英文字母。

思路

这道题的做法比较经典。

我们将 \(s_i\) 建出 Trie 树,那么如果一个字符串是美好的,我们要让 Trie 树上每一层的其他字符都比这个字符串在这一层的字符小。然后就可以了。

但是会出现我们无法找到这样的方案的情况。有这两种:

  • 存在另一个字符串 \(t\) 是这个字符串 \(s\) 的前缀,这样肯定没有方案。因为无论如何都满足 \(t<s\)。
  • 出现矛盾。例如,我们在前面认为 \(x<y\),后面又认为 \(y<x\)。这样就出现了矛盾,无解。

第一种情况判断比较简单。我们给字符串结尾打上标记,遍历时看看有没有标记即可。注意不要把自己的标记算上了。

第二种情况,我们可以连边 \((x,y)\)。然后就是判断一个有向图有没有环,Tarjan 求强连通分量解决即可。

时间复杂度 \(O(|S|+26n)\)。

代码

#include <bits/stdc++.h>
using namespace std;

int n;
const int N = 300005;
int trie[N][26],stop[N],tot;

void insert(const string &x){
    int cur=0;
    for(char i : x){
        if(!trie[cur][i-'a']) trie[cur][i-'a']=(++tot);
        cur=trie[cur][i-'a'];
    }
    stop[cur]++;
}

bool g[30][30];
int dfn[30],low[30],dfncnt,ecc;
bool vis[30];
stack<int> sta;

void tarjan(int u){
    dfn[u]=low[u]=(++dfncnt);vis[u]=1;
    sta.push(u);
    for(int v=0;v<26;v++){
        if(!g[u][v]) continue;
        if(!dfn[v]){
            tarjan(v);low[u]=min(low[u],low[v]);
        }
        else if(vis[v]) low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        ecc++;
        while(sta.top()!=u){
            vis[sta.top()]=0;sta.pop();
        }
        sta.pop();vis[u]=0;
    }
}

void clear(){
    memset(g,0,sizeof(g));
    memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));dfncnt=ecc=0;
    while(!sta.empty()) sta.pop();
}

bool solve(const string &x){
    clear();
    int cur=0;
    for(int i=0;i<x.size();i++){
        if(stop[cur]) return false;
        for(int j=0;j<26;j++){
            if(trie[cur][j]&&x[i]!=(j+'a')) g[x[i]-'a'][j]=1;
        }
        cur=trie[cur][x[i]-'a'];
    }
    for(int i=0;i<26;i++){
        if(!dfn[i]) tarjan(i);
    }
    return ecc==26;
}

string s[N];
vector<string> ret;

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i];insert(s[i]);
    }
    for(int i=1;i<=n;i++){
        if(solve(s[i])) ret.push_back(s[i]);
    }
    cout<<ret.size()<<'\n';
    for(string s : ret) cout<<s<<'\n';
    return 0;
}

标签:USACO12DEC,cur,P3065,int,30,leq,trie,字符串,First
From: https://www.cnblogs.com/zheyuanxie/p/p3065.html

相关文章

  • Laravel的ORM模型的find(),findOrFail(),first(),firstOrFail(),get(),list(),toArray()之间
    阅读目录​​get()后连缀方式添加getList方法​​​​get_object_vars—返回由对象属性组成的关联数组​​​​get()方法后添加getList()方法​​find($id)需要一个......
  • 2019南昌网络赛 E. Magic Master (模拟) The 2019 Asia Nanchang First Round Online P
     Johnisnotonlyamagicmasterbutalsoashufflingmaster.  Famousthoughheis,helikesinteractingwithhisfansbyplayingagamewithhisfantasti......
  • code First 迁移
    你可能先使用codeFirst先生成了上下文,然后添加了一些数据进去,这个时候你想再其中的某一个类加几个字段,但你想继续保留在数据库中的数据。因为这个时候之前的那几个初始化......
  • 23/1/31-LeetCode 28: Find the Index of the First Occurrence in a String
    LeetCode28:FindtheIndexoftheFirstOccurrenceinaString心路历程一开始迅猛完成了一个版本,然后忽略了这种情况"mississippi""issip"这样我会第一个在ssi......
  • OSPF Open Shortest Path First
    OSPF(OpenShortestPathFirst开放式最短路径优先)是一个内部网关协议(InteriorGatewayProtocol,简称IGP),用于在单一自治系统(AutonomousSystem,AS)内决策路由。是对链......
  • 在asp.net core web api中添加efcore使用codefirst
    首先创建webapi项目,我这里使用的版本是.net6  在nuget中添加对应的工具包 红框标出来的是对应的数据库扩展包,mysql用mysql版,sqlserver用sqlserver版,选择正确的版......
  • G1(Garbage-First)回收器
    G1(Garbage-First)回收器是在JDK1.7中正式使用的全新垃圾回收器,G1拥有独特的垃圾回收策略,从分代上看,G1依然属于分代垃圾回收器,它会区分年代和老年代,依然有eden和survivor区......
  • 洛谷P3654 First Step题解
    这是一道暴力枚举。 大致题意:R行C列的棋盘要放下长度为K的线段,“#”表示无法放置,问有多少种放置方法。直接贴代码:#include<bits/stdc++.h>usingnamespacestd;i......
  • :first-child 伪类一句话解释
    关键词不起作用选不到失败解释input:first-child要求既是input元素,而且是兄弟节点中的第一个如果要找第一个input元素,那么用input:first-of-type如果要用first-ch......
  • 818 Div 2.F. Madoka and The First Session
    Problem-F-Codeforces818Div2.F.MadokaandTheFirstSession思路:不妨转化一下题意:将条件转化为:\(b_v+1,b_v+1\),然后使得其中一个-2那么在\(a\)上就是使\(a_......