HDU 6208 The Dominator of Strings ——(青岛网络赛,AC自动机)

  最长的才可能成为答案,那么除了最长的以外全部insert到自动机里,再拿最长的去match,如果match完以后cnt全被清空了,那么这个最长串就是答案。事实上方便起见这个最长串一起丢进去也无妨,而且更好写(时间也没有慢特别多)。

  另外需要注意的一点是init()里头的memset只需要清空之前用过的节点而不是所有节点,这是经常被卡的一点。

  代码如下:

  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <string.h>
  4 #include <queue>
  5 #include <vector>
  6 using namespace std;
  7 const int MAX_N = 100000 + 50;
  8 const int MAX_Tot = 100000 + 50;
  9
 10 struct Aho
 11 {
 12     struct state
 13     {
 14         int nxt[26];
 15         int fail,cnt;
 16     }stateTable[MAX_Tot];
 17
 18     int size;
 19
 20     queue<int> que;
 21
 22     void init()
 23     {
 24         while(que.size()) que.pop();
 25         for(int i=0;i<size;i++)
 26         {
 27             memset(stateTable[i].nxt,0,sizeof(stateTable[i].nxt));
 28             stateTable[i].fail = stateTable[i].cnt = 0;
 29         }
 30         size = 1;
 31     }
 32
 33     void insert(char *s)
 34     {
 35         int n = strlen(s);
 36         int now = 0;
 37         for(int i=0;i<n;i++)
 38         {
 39             char c = s[i];
 40             if(!stateTable[now].nxt[c-‘a‘])
 41                 stateTable[now].nxt[c-‘a‘] = size++;
 42             now = stateTable[now].nxt[c-‘a‘];
 43         }
 44         stateTable[now].cnt++;
 45     }
 46
 47     void build()
 48     {
 49         stateTable[0].fail = -1;
 50         que.push(0);
 51
 52         while(que.size())
 53         {
 54             int u = que.front();que.pop();
 55             for(int i=0;i<26;i++)
 56             {
 57                 if(stateTable[u].nxt[i])
 58                 {
 59                     if(u == 0) stateTable[stateTable[u].nxt[i]].fail = 0;
 60                     else
 61                     {
 62                         int v = stateTable[u].fail;
 63                         while(v != -1)
 64                         {
 65                             if(stateTable[v].nxt[i])
 66                             {
 67                                 stateTable[stateTable[u].nxt[i]].fail = stateTable[v].nxt[i];
 68                                 break;
 69                             }
 70                             v = stateTable[v].fail;
 71                         }
 72                         if(v == -1) stateTable[stateTable[u].nxt[i]].fail = 0;
 73                     }
 74                     que.push(stateTable[u].nxt[i]);
 75                 }
 76             }
 77         }
 78     }
 79
 80     //bool mark[MAX_Tot];
 81     void Get(int u)
 82     {
 83         while(u)
 84         {
 85             if(stateTable[u].cnt == -1) break;
 86             stateTable[u].cnt = -1;
 87             u = stateTable[u].fail;
 88         }
 89     }
 90
 91     int match(char *s)
 92     {
 93         //memset(mark, 0, sizeof mark);
 94         int n = strlen(s);
 95         int res = 0, now = 0;
 96         for(int i=0;i<n;i++)
 97         {
 98             char c = s[i];
 99             if(stateTable[now].nxt[c-‘a‘]) now = stateTable[now].nxt[c-‘a‘];
100             else
101             {
102                 int p = stateTable[now].fail;
103                 while(p != -1 && stateTable[p].nxt[c-‘a‘] == 0) p = stateTable[p].fail;
104                 if(p == -1) now = 0;
105                 else now = stateTable[p].nxt[c-‘a‘];
106             }
107
108             Get(now);
109         }
110         for(int i=1;i<size;i++) if(stateTable[i].cnt > 0) return 0;
111         return 1;
112     }
113 }aho;
114
115 int T,n;
116 char s[MAX_N], t[MAX_N];
117
118 int main()
119 {
120     int T;scanf("%d",&T);
121     while(T--)
122     {
123         vector<char> v;
124         aho.init();
125         scanf("%d",&n);
126         int maxn = 0;
127         for(int i=1;i<=n;i++)
128         {
129             scanf("%s",s);
130             //aho.insert(s);
131             int sz = strlen(s);
132             for(int j=0;j<sz;j++) v.push_back(s[j]);
133             v.push_back(‘#‘);
134             if(sz > maxn)
135             {
136                 maxn = sz;
137                 strcpy(t, s);
138             }
139         }
140         int tot = 0;
141         for(int i=0;i<v.size();i++)
142         {
143             if(v[i] == ‘#‘)
144             {
145                 s[tot++] = 0;
146                 tot = 0;
147                 if(strcmp(s, t)) aho.insert(s);
148             }
149             else s[tot++] = v[i];
150         }
151         aho.build();
152         int ans = aho.match(t);
153         if(ans) puts(t);
154         else puts("No");
155     }
156 }
时间: 2024-10-12 22:48:12

HDU 6208 The Dominator of Strings ——(青岛网络赛,AC自动机)的相关文章

HDU 5880 Family View (2016 青岛网络赛 C题,AC自动机)

题目链接  2016 青岛网络赛  Problem C 题意  给出一些敏感词,和一篇文章.现在要屏蔽这篇文章中所有出现过的敏感词,屏蔽掉的用$'*'$表示. 建立$AC$自动机,查询的时候沿着$fail$指针往下走,当匹配成功的时候更新$f[i]$ $f[i]$表示要屏蔽以第$i$个字母结尾的长度为$f[i]$的字符串. 原文地址:https://www.cnblogs.com/cxhscst2/p/8452147.html

HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)

题目链接  2016 Qingdao Online Problem I 题意  在一棵给定的树上删掉一条边,求剩下两棵树的树的直径中较长那的那个长度的期望,答案乘上$n-1$后输出. 先把原来那棵树的直径求出来.显然删掉的边不是这条直径上的边,那么这时答案就是这条直径的长度. 否则就是直径的某个端点到某一个点(要求连通)的距离的最大值. 在整条链上做两次$DP$之后枚举取较大值即可. #include <bits/stdc++.h> using namespace std; #define r

HDU - 4734 F(x) (2013成都网络赛,数位DP)

题意:求0-B的满足<=F[A]的所有可能 思路:数位DP,记忆化搜索 #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; int A, B; int dp[20][200000]; int bit[20]; int dfs(int cur, int num, int flag) { if (cur == -

HDU 5875 Function -2016 ICPC 大连赛区网络赛

题目链接 网络赛的水实在太深,这场居然没出线zzz,差了一点点,看到这道题的的时候就剩半个小时了.上面是官方的题意题解,打完了才知道暴力就可以过,暴力我们当时是想出来了的,如果稍稍再优化一下估计就过了zzz.去年有一场现场赛也是n=1000,n^3过了,看来关键时刻实在做不出来就得大胆暴力啊. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+5; int a[maxn]

2016 年青岛网络赛---Family View(AC自动机)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5880 Problem Description Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and social networking services. A family view

hdu 5164 Matching on Array (用map实现的ac自动机)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5164 题意: 给出长度为n一个母串,给出m个长度为ki子串,匹配的条件是比率相同,如子串4 8 能和 1 2 4匹配.问所有子串在母串中出现多少次. 限制: 1 <= n,m <= 1e5 1 <= ki <= 300000 思路: 赤裸裸的ac自动机啊,不过next数组用map来实现,出题人脑洞真大. 这里有一点还要注意,hdu的g++,结构体里面不能开太大的东西,要不然他ce了还

hdu 5881 Tea (2016 acm 青岛网络赛)

原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5881 Tea Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 451    Accepted Submission(s): 124 Problem Description Tea is good. Tea is life. Tea is e

HDU 5008 Boring String Problem(西安网络赛B题)

HDU 5008 Boring String Problem 题目链接 思路:构造后缀数组,利用height的数组能预处理出每个字典序开始的前缀和有多少个(其实就是为了去除重复串),然后每次二分查找相应位置,然后在往前往后找一下sa[i]最小的 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int

2016 年青岛网络赛---Tea

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5881 Problem Description Tea is good. Tea is life. Tea is everything. The balance of tea is a journey of pursuing balance of the universe. Alice knows that. Alice wants to teach you the art of pouring te