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.
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 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。