首页 > 其他分享 >假的字符串 Trie+拓扑排序

假的字符串 Trie+拓扑排序

时间:2024-08-01 08:57:48浏览次数:10  
标签:ch Trie auto 拓扑 define int 排序 字典

假的字符串 Trie+拓扑排序

题目链接

题意

给定n个字符串,互不相等,你可以任意指定字符之间的大小关系(即重定义字典序),求有多少个串可能成为字典序最小的串,并输出它们。

思路

我们可以对每个字符串单独判断,考虑当前 \(s_i\) 为字典序最小的串。那么首先要满足的条件就是 \(s_i\) 的前缀不能出现在字典中,前缀的字典序一定比 \(s_i\) 小。接着我们考虑其他字符串怎么判断?不妨将所有串插入到Trie中,那么我们可以遍历 \(s_i\) 的每个节点,如果当前节点有其他子节点,那么说明 \(s_i\) 的下一个字母的字典序一定小于其余字母。因此,我们就会得到很多对偏序关系。只要偏序关系不出现矛盾,那么就一定可以构造出新的字符大小关系来保证 \(s_i\) 是字典中字典序最小的串。那么我们可以对这些偏序关系建图,然后拓扑排序判断是否有环即可。

代码

#include<bits/stdc++.h>

using namespace std;

#define ff first
#define ss second
#define pb push_back
#define all(u) u.begin(), u.end()
#define endl '\n'
#define debug(x) cout<<#x<<":"<<x<<endl;

typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 3e5 + 10, M = 105;
const int mod = 1e9 + 7;
const int cases = 0;

//Trie
struct Trie{
   int ch[N][26];
   int cnt[N];
   int idx=0;
   void insert(string s){
      int p=0;
      for(auto c:s){
         int j=c-'a';
         if(!ch[p][j]) ch[p][j]=++idx;
         p=ch[p][j];
      }
      cnt[p]++;
   }
   int query(string s){
      int p=0;
      for(auto c:s){
         int j=c-'a';
         if(!ch[p][j]) return 0;
         p=ch[p][j];
      }
      return cnt[p];
   }
}trie;

void Showball(){
   int n;
   cin>>n;
   vector<string> a(n);
   for(int i=0;i<n;i++){
      cin>>a[i];
      trie.insert(a[i]);
   }
   
   auto check=[&](string s){
      vector<int> e[26];
      vector<int> d(26,0);
      int p=0;
      for(auto c:s){
         int j=c-'a';
         for(int i=0;i<26;i++){
            if(trie.ch[p][i]){
               if(i==j) continue;
               e[j].pb(i);
               d[i]++;
            }
         }
         if(trie.cnt[p]) return false;
         p=trie.ch[p][j];
      }
      //topo判断环
      int cnt=0;
      queue<int> q;
      for(int i=0;i<26;i++) if(!d[i]) q.push(i);
      while(!q.empty()){
         int u=q.front();q.pop();
         cnt++;
         for(auto v:e[u]){
            if(!--d[v]) q.push(v);
         }
      }
      return cnt==26;
   };

   vector<string> ans;
   for(auto s:a){
      if(check(s)) ans.pb(s);
   }
   cout<<ans.size()<<endl;
   for(auto s:ans) cout<<s<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    if(cases) cin>>T;
    while(T--)
    Showball();
    return 0;
}

标签:ch,Trie,auto,拓扑,define,int,排序,字典
From: https://www.cnblogs.com/showball/p/18335891

相关文章

  • LeetCode 3111. 覆盖所有点的最少矩形数目(贪心、排序)
    题目:3111.覆盖所有点的最少矩形数目思路:只需关注横坐标,对横坐标进行升序排序,然后进行贪心,求得最少的矩阵数量classSolution{public:intminRectanglesToCoverPoints(vector<vector<int>>&points,intw){vector<int>v;for(inti=0;i<poi......
  • java算法递归算法之选择排序
    快速排序的原理就是将数组进行分区,分为三个区,然后如果每个区都是有序数组的话,就已经达成了我们的目标小于基准值的数组组成的子数组基准值大于基准值的数组组成的子数组因此我们需要重复以上的步骤,分别对1和3也选择基准值进行分区,直到数组中最后只剩0个或者1个,那么就达到目标......
  • 数组(二)———数组的排序算法①
    目录冒泡排序基本步骤:复杂度分析实现示例(Java):选择排序基本步骤:复杂度分析实现示例(Java):插入排序基本步骤:复杂度分析实现示例(Java):希尔排序基本步骤:复杂度分析实现示例(Java):归并排序基本步骤:复杂度分析实现示例(Java):冒泡排序定义:冒泡排序(BubbleSort)是......
  • 【数据结构】排序算法(快速排序、归并排序、排序算法总结)
    当你清楚的知道自己想要什么,并且意愿非常强烈的时候,你总会有办法得到的。......
  • 排序
    排序1.冒泡排序voidbubblesort1(int*arr,unsignedintlen){ //长度小于2就不用排序了 if(len<2)return; for(inti=0;i<len-1;i++){ for(intj=0;j<len-1-i;j++){ if(arr[j]>arr[j+1]) swap(arr[j+1],arr[j]); } }}//......
  • 【初阶数据结构】11.排序(2)
    文章目录2.3交换排序2.3.1冒泡排序2.3.2快速排序2.3.2.1hoare版本2.3.2.2挖坑法2.3.2.3lomuto前后指针2.3.2.4非递归版本2.4归并排序2.5测试代码:排序性能对比2.6非比较排序2.6.1计数排序3.排序算法复杂度及稳定性分析2.3交换排序交换排序基本思想:......
  • 【算法 Java】排序
    排序所有的排序以从小到大排序为例模板题:牛客-简单的排序排序算法的稳定性体现在相同数值元素的相对位置会不会随排序改变,如果改变则不稳定,如果不改变则稳定冒泡排序比较相邻的元素。如果第一个比第二个大,就交换他们两个。越大的元素会经由交换慢慢"浮"到数列的末端。时间复......
  • 数据结构之八大排序(上)
    找往期文章包括但不限于本期文章中不懂的知识点:个人主页:我要学编程(ಥ_ಥ)-CSDN博客所属专栏:数据结构(Java版) 目录排序的相关介绍直接插入排序 希尔排序(缩小增量排序)选择排序堆排序冒泡排序 排序的相关介绍排序的概念:所谓排序,就是使一串记录,按照其中的某个或......
  • C语言——数组和排序
    C语言——数组和排序数组数组的概念数组的初始化数组的特点排序选择排序冒泡排序插入排序二分查找数组数组的概念数组是一组数据;数组是一组相同类型的数据或变量的集合;应用场景:用于批量的处理多个数据;语法:类型说明符数组名[常量表达式]类型说明符也就......
  • Luogu P1983 车站分级 题解 [ 绿 ] [ 拓扑排序 ] [ 图论建模 ] [ 虚点 ]
    车站分级:很好的拓扑排序题,细节有点多。图论建模首先观察对于一条线路,我们可以从中直接得到什么信息:假设这条线路的开头为\(st\),结尾为\(ed\),那么在\([st,ed]\)的车站中,没有被选入线路的点一定比选入线路的点的级数至少少\(1\)。对于这一点条件,我们就可以建模了。......