hdu6208 The Dominator of Strings

地址:

题目:

The Dominator of Strings

Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 857    Accepted Submission(s): 264


Problem Description
Here you have a set of strings. A dominator is a string of the set dominating all strings else. The string S is dominated by T if S is a substring of T.
 

 

Input
The input contains several test cases and the first line provides the total number of cases.
For each test case, the first line contains an integer N indicating the size of the set.
Each of the following N lines describes a string of the set in lowercase.
The total length of strings in each case has the limit of 100000.
The limit is 30MB for the input file.
 

 

Output
For each test case, output a dominator if exist, or No if not.
 

 

Sample Input
3 10 you better worse richer poorer sickness health death faithfulness youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness 5 abc cde abcde abcde bcde 3 aaaaa aaaab aaaac
 

 

Sample Output
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness abcde No
 

 

Source
 
思路:
  这题数据好像很水,做法多的飞起:ac自动机能过,后缀自动机能过,kmp也能过(好像有特殊技巧才可以),暴力hash也能过。
  我是ac自动机做的,看题后写完1a了,还以为是sb题,发现我也是跑了2800ms,也是卡过去的,还好提前关了同步。
  ac自动机做法就是,把最长串以外的串建立ac自动机,然后让最长串在上面跑就好了。
  讲道理这复杂度也就是:t*所有串的总长度=t*1e5,常数大概20或30左右吧(瞎分析)
  ps:赛后测了下同一份也就跑了2000ms,比赛时却跑了2800ms,这服务器。。。。又交了几发,发现服务器不稳定,一般是2200ms左右
  再讲个后缀自动机做法:把最长串串建立sam,然后让其他串在上面跑就好了,这个做法快的飞起,跑了560ms
ac自动机代码:
  1 #include <queue>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <string>
  5 #include <iostream>
  6 using namespace std;
  7 
  8 struct AC_auto
  9 {
 10     const static int LetterSize = 26;
 11     const static int TrieSize = 26 * ( 1e5 + 50);
 12 
 13     int tot,root,fail[TrieSize],end[TrieSize],next[TrieSize][LetterSize];
 14 
 15     int newnode(void)
 16     {
 17         memset(next[tot],-1,sizeof(next[tot]));
 18         end[tot] = 0;
 19         return tot++;
 20     }
 21 
 22     void init(void)
 23     {
 24         tot = 0;
 25         root = newnode();
 26     }
 27 
 28     int getidx(char x)
 29     {
 30         return x - 'a';
 31     }
 32 
 33     void insert(string &ss)
 34     {
 35         int len = ss.length();
 36         int now = root;
 37         for(int i = 0; i < len; i++)
 38         {
 39             int idx = getidx(ss[i]);
 40             if(next[now][idx] == -1)
 41                 next[now][idx] = newnode();
 42             now = next[now][idx];
 43         }
 44         end[now]++;
 45     }
 46 
 47     void build(void)
 48     {
 49         queue<int>Q;
 50         fail[root] = root;
 51         for(int i = 0; i < LetterSize; i++)
 52             if(next[root][i] == -1)
 53                 next[root][i] = root;
 54             else
 55                 fail[next[root][i]] = root,Q.push(next[root][i]);
 56         while(Q.size())
 57         {
 58             int now = Q.front();Q.pop();
 59             for(int i = 0; i < LetterSize; i++)
 60             if(next[now][i] == -1)   next[now][i] = next[fail[now]][i];
 61             else
 62                 fail[next[now][i]] = next[fail[now]][i],Q.push(next[now][i]);
 63         }
 64     }
 65 
 66     int match(string &ss)
 67     {
 68         int len,now,res;
 69         len = ss.length(),now = root,res = 0;
 70         for(int i = 0; i < len; i++)
 71         {
 72             int idx = getidx(ss[i]);
 73             int tmp = now = next[now][idx];
 74             while(tmp)
 75             {
 76                 res += end[tmp];
 77                 end[tmp] = 0;//按题目修改
 78                 tmp = fail[tmp];
 79             }
 80         }
 81         return res;
 82     }
 83     void debug()
 84     {
 85         for(int i = 0;i < tot;i++)
 86         {
 87             printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
 88             for(int j = 0;j < LetterSize;j++)
 89                 printf("%3d",next[i][j]);
 90             printf("]\n");
 91         }
 92     }
 93 };
 94 AC_auto ac;
 95 string ss[100002];
 96 int main(void)
 97 {
 98     std::ios::sync_with_stdio(0);
 99     cin.tie(0);
100     //freopen("in.acm","r",stdin);
101     int t,n,id;cin>>t;
102     while(t--)
103     {
104         id=1;
105         ac.init();
106         cin>>n>>ss[1];
107         for(int i=2;i<=n;i++)   cin>>ss[i],id=ss[id].length()>ss[i].length()?id:i;
108         for(int i=1;i<=n;i++)
109         if(i!=id)
110             ac.insert(ss[i]);
111         ac.build();
112         if(ac.match(ss[id])==n-1)
113             cout<<ss[id]<<"\n";
114         else
115             cout<<"No\n";
116     }
117     return 0;
118 }

 sam做法:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 struct SAM
 6 {
 7     static const int MAXN = 100001<<1;//大小为字符串长度两倍
 8     static const int LetterSize = 27;
 9 
10     int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
11     int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组
12 
13     void init( void)
14     {
15         last = tot = 1;
16         len[1] = 0;
17         memset(ch[0],0,sizeof ch[0]);
18         memset(cnt,0,sizeof cnt);
19     }
20 
21     void add(int x)
22     {
23         int p = last, np = last = ++tot;
24         len[np] = len[p] + 1, cnt[last] = 1;
25         memset(ch[np],0,sizeof ch[np]);
26         while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
27         if( p == 0)
28             fa[np] = 1;
29         else
30         {
31             int q = ch[p][x];
32             if( len[q] == len[p] + 1)
33                 fa[np] = q;
34             else
35             {
36                 int nq = ++tot;
37                 memcpy( ch[nq], ch[q], sizeof ch[q]);
38                 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
39                 while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
40             }
41         }
42     }
43 
44     void toposort( void)
45     {
46         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
47         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
48         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
49         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
50         for(int i = tot; i; i--)   cnt[fa[tp[i]]] += cnt[tp[i]];
51     }
52 
53     bool match(string &s)
54     {
55         for(int i=0,p=1;i<s.length();p=ch[p][s[i]-'a'],i++)
56         if(!ch[p][s[i]-'a'])
57             return 0;
58         return 1;
59     }
60 } sam;
61 string ss[100001];
62 int main(void)
63 {
64     ios::sync_with_stdio(0);
65     cin.tie(0);
66     int t;cin>>t;
67     while(t--)
68     {
69         int n,ff=1,id=1;
70         cin>>n;
71         for(int i=1;i<=n;i++)   cin>>ss[i],id=(ss[i].length()>ss[id].length()?i:id);
72         sam.init();
73         for(int i=1;i<=n;i++)
74         if(i!=id)
75         {
76             for(int j=0;j<ss[i].length();j++)    sam.add(ss[i][j]-'a');
77             sam.add(26);
78         }
79         for(int i=n;i&&ff;i--)
80         if(i!=id&&!sam.match(ss[i]))
81             ff=0;
82         if(ff)  cout<<ss[id]<<"\n";
83         else    cout<<"No\n";
84     }
85     return 0;
86 }

 

 
posted @ 2017-09-17 22:28  weeping  阅读(234)  评论(0编辑  收藏  举报