码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-02-09 17:32:05      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:style   scanf   关系   pac   continue   tin   blog   head   字典   

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

题意:

给定n个总长不超过m的互不相同的字符串,现在你可以任意指定字符之间的大小关系。问有多少个串可能成为字典
序最小的串,并输出这些串。n <= 30,000 , m <= 300,000
分析:
首先不考虑大小关系,如果一个串是另一个串的前缀,那么另一个串一定不能成为字典序最小的串,我们可以用trie树很好的解决。
考虑前缀相同的情况,这个串在前缀后的字符应该和含有相同前缀的串在前缀后的字符有明确的大小关系,根据这个大小关系连边,我们用拓扑排序判断是否矛盾。
以上都满足则可以成为字典序最小的串。
代码:
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <queue>
 5 using namespace std;
 6 #define N 30050
 7 struct A
 8 {
 9     int son[30],end;
10 }t[N*10];
11 int n,tot,head[30],to[N],nxt[N],c[30],cnt=1,ans[30010];
12 char s[30010][310];
13 void add(int u,int v)
14 {
15     to[++cnt]=v;
16     nxt[cnt]=head[u];
17     head[u]=cnt;
18     c[v]++;
19 }
20 void insert(int x)
21 {
22     int p=1;
23     int len=strlen(s[x]+1);
24     for(int i=1;i<=len;i++)
25     {
26         int id=s[x][i]-a+1;
27         if(!t[p].son[id])t[p].son[id]=++cnt;
28         p=t[p].son[id];
29     }
30     t[p].end=1;
31 }
32 bool search(int x)
33 {
34     int p=1;
35     int len=strlen(s[x]+1);
36     for(int i=1;i<=len;i++)
37     {
38         if(t[p].end)return 0;
39         int id=s[x][i]-a+1;
40         for(int j=1;j<=26;j++)
41         {
42             if(j!=id&&t[p].son[j])
43             {
44                 add(id,j);
45             }
46         }
47         p=t[p].son[id];
48     }
49     return 1;
50 }
51 bool topsort()
52 {
53     queue <int> q;
54     for(int i=1;i<=26;i++)if(c[i]==0)q.push(i);
55     while(!q.empty())
56     {
57         int x=q.front();q.pop();
58         for(int i=head[x];i;i=nxt[i])
59         {
60             c[to[i]]--;
61             if(c[to[i]]==0)q.push(to[i]);
62         }
63     }
64     for(int i=1;i<=26;i++)if(c[i])return 0;
65     return 1;
66 }
67 int main()
68 {
69     scanf("%d",&n);
70     for(int i=1;i<=n;i++)
71     {
72         scanf("%s",s[i]+1);
73         insert(i);
74     }
75     for(int i=1;i<=n;i++)
76     {
77         memset(head,0,sizeof(head));
78         memset(c,0,sizeof(c));cnt=0;
79         if(!search(i))continue;
80         if(!topsort())continue;
81         ans[++tot]=i;
82     }
83     printf("%d\n",tot);
84     for(int i=1;i<=tot;i++)
85     {
86         printf("%s\n",s[ans[i]]+1);
87     }
88 }

 

 

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

标签:style   scanf   关系   pac   continue   tin   blog   head   字典   

原文地址:https://www.cnblogs.com/suika/p/8435786.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!