BZOJ3012 : [Usaco2012 Dec]First!

建立Trie,那么成为答案的串必须满足其终止节点到根路径上没有其它点。

对于Trie上每个节点维护一个bitset,表示哪些字符必须在哪些字符之前。

每到达一个可能成为答案的终止节点,对图进行拓扑排序进行判定。

时间复杂度$O(26^2N+26|S|)$。

#include<cstdio>
#include<cstring>
#define rep(i) for(int i=0;i<26;i++)
const int N=30010,M=300010;
int n,i,j,k,x,cnt,len,st[N],en[N],fin[N],ans;
int tot,son[M][26],id[M],v[M],f[M][26];
int g[26][26],d[26],q[30];
char s[M],text[M];
void dfs(int x){
  if(id[x]){
    rep(i)for(int j=d[i]=0;j<26;j++)g[i][j]=0;
    rep(i)rep(j)if(i!=j&&(f[x][i]>>j&1))g[i][j]=1,d[j]++;
    int h=1,t=0;
    rep(i)if(!d[i])q[++t]=i;
    while(h<=t){
      int x=q[h++];
      rep(i)if(g[x][i])if(!(--d[i]))q[++t]=i;
    }
    if(t==26)fin[id[x]]=1,ans++;
    return;
  }
  rep(i)if(son[x][i]){
    int y=son[x][i];
    rep(j)f[y][j]=f[x][j];
    f[y][i]|=v[x];
    dfs(y);
  }
}
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++){
    scanf("%s",s);
    len=strlen(s);
    st[i]=cnt;
    for(j=x=0;j<len;x=son[x][k],j++)if(!son[x][k=text[cnt++]=s[j]-‘a‘])son[x][k]=++tot,v[x]|=1<<k;
    id[x]=i;
    en[i]=cnt;
  }
  dfs(0);
  for(printf("%d\n",ans),i=1;i<=n;i++)if(fin[i]){
    for(j=st[i];j<en[i];j++)putchar(text[j]+‘a‘);
    puts("");
  }
  return 0;
}

  

时间: 2024-11-05 14:49:00

BZOJ3012 : [Usaco2012 Dec]First!的相关文章

BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )

子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 ------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; #define M(l, r) (((l) + (r)) >> 1) const int maxn = 200009; typedef long long ll; inline ll

【BZOJ3011】[Usaco2012 Dec]Running Away From the Barn 可并堆

[BZOJ3011][Usaco2012 Dec]Running Away From the Barn Description It's milking time at Farmer John's farm, but the cows have all run away! Farmer John needs to round them all up, and needs your help in the search. FJ's farm is a series of N (1 <= N <=

bzoj3011[Usaco2012 Dec]Running Away From the Barn*

bzoj3011[Usaco2012 Dec]Running Away From the Barn 题意: 给出以1号点为根的一棵有边权的树,问每个点的子树中与它距离小于l的点有多少个.树的大小≤200000. 题解: 每个节点维护一个带标记可并堆,dfs时对子节点的堆加上当前节点到该子节点的边权,之后令其与当前节点的堆合并. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #i

BZOJ 3011 Usaco2012 Dec Running Away From the Barn 可并堆

题目大意:给定一棵有根树,求以每个点为根的子树中有多少点到它的距离不超过l 第一眼是可并堆- - 于是怒写- - 管它正解是啥- - 从下到上维护可并大根堆 键值是该点到当前根节点的距离 一旦堆顶剪枝大于l就弹顶 时间复杂度O(nlogn) 什么?你说将整个堆都加上一个值? 打标记不就好了- - 毫无疑问可并堆是可以打标记的- - 此外我的随机堆写if(flag^=1)就T写if(rand()&1)就秒过是什么鬼- - #include <cstdio> #include <cs

BZOJ 3012 [Usaco2012 Dec]First! wzq脑洞hash树(正解trie树)

博客风格转化计划实验篇2 题意: 给n(n<=30000)个字符串,所有字符串长度加起来不超过300000(字符串只含有小写字母). 求解哪些字符串可以称作第一字符串. 一个字符串能被称为第一字符串的条件为存在一种字典序使它排在第一名. 方法: wzq脑洞hash树-.. 然而并没有trie树优越. 并且我脑洞的这个树好处有啥:暂且不知道. 坏处有啥:很容易被卡,自带常数. 所以为什么要这么写?只是因为我跟wjc说这题我特么一定要用带hash的东西搞过去! *目标达成√ 解析: 对于以下内容,请

BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序

题意: 给定n个总长不超过m的互不相同的字符串,现在你可以任意指定字符之间的大小关系.问有多少个串可能成为字典 序最小的串,并输出这些串.n <= 30,000 , m <= 300,000 分析: 首先不考虑大小关系,如果一个串是另一个串的前缀,那么另一个串一定不能成为字典序最小的串,我们可以用trie树很好的解决. 考虑前缀相同的情况,这个串在前缀后的字符应该和含有相同前缀的串在前缀后的字符有明确的大小关系,根据这个大小关系连边,我们用拓扑排序判断是否矛盾. 以上都满足则可以成为字典序最小

2620: [Usaco2012 Mar]Haybale Restacking

2620: [Usaco2012 Mar]Haybale Restacking Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 201  Solved: 111[Submit][Status][Discuss] Description Farmer John has just ordered a large number of bales of hay. He would like to organize these into N piles (1

3016: [Usaco2012 Nov]Clumsy Cows

3016: [Usaco2012 Nov]Clumsy Cows Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 91  Solved: 69[Submit][Status][Discuss] Description Bessie the cow is trying to type a balanced string of parentheses into her new laptop, but she is sufficiently clumsy

[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1297  Solved: 705 [Submit][Status][Discuss] Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". John的牛奶按质量可以被赋予一个0到100