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
 
【题意】:给n个串,问是否有一个串,包含了其他所有串。
【分析】:显然若这样的字符串存在就一定是最长的那个,然后考虑下AC自动机的入门题HDU2222,然后思路就清晰了,首先构建自动机,然后选出长度最长的一串来跑一遍自动机,统计所有字符串出现的个数,不重复统计,然后个数!=n就是No。
【代码*3】:
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<queue>
  4. #include<string>
  5. #include<iostream>
  6. #define maxlen 100005
  7. using namespace std;
  8. int n;
  9. int nxt[maxlen][],FAIL[maxlen],edd[maxlen],root,L;//nxt记录节点,在这里edd指针代表以当前节点为字符串尾的字符串个数
  10. int mark[maxlen];
  11. int newnode()
  12. {
  13. for(int i=;i<;i++)
  14. nxt[L][i]=-;//节点连接的边初始化为-1
  15. edd[L]=;
  16. mark[L]=;
  17. return L++;
  18. }
  19. void init()
  20. {
  21. L=;
  22. root=newnode();
  23. }
  24.  
  25. void insert(char buf[],int l)//trie树的建立
  26. {
  27. int now=root;
  28. for(int i=;i<l;i++)
  29. {
  30. if(nxt[now][buf[i]-'a']==-)nxt[now][buf[i]-'a']=newnode();
  31. now=nxt[now][buf[i]-'a'];
  32. }
  33. edd[now]++;
  34. }
  35. void build()//建立ac自动机
  36. {
  37. queue<int>que;
  38. for(int i=;i<;i++)
  39. {
  40. if(nxt[root][i]==-)nxt[root][i]=root;
  41. else //若有连边则将节点加入队列 ,并将FAIL指针指向root
  42. {
  43. FAIL[nxt[root][i]]=root;
  44. que.push(nxt[root][i]);
  45. }
  46. }
  47. while(!que.empty())
  48. {
  49. int now=que.front();
  50. que.pop();
  51. for(int i=;i<;i++)
  52. {
  53. if(nxt[now][i]==-) //若无连边,则将该边指向当前节点FAIL指针指向的相应字符连接的节点
  54. nxt[now][i]=nxt[FAIL[now]][i];
  55. else //若有连边,则将儿子节点的FAIL指针指向当前节点FAIL指针指向相应字符接的节点
  56. {
  57. FAIL[nxt[now][i]]=nxt[FAIL[now]][i];
  58. que.push(nxt[now][i]); //加入队列继续遍历
  59. }
  60. }
  61. }
  62. }
  63. int query(char buf[],int l)
  64. {
  65. int now=root;
  66. int res=;
  67. for(int i=;i<l;i++)
  68. {
  69. now=nxt[now][buf[i]-'a'];
  70. int temp=now;
  71. while(temp!=root&&mark[temp]==)//根据题目要求改变形式
  72. {
  73. res+=edd[temp];
  74. edd[temp]=;
  75. mark[temp]=;
  76. temp=FAIL[temp];
  77. }
  78. }
  79. return res; //在这里返回的是匹配到的模式串的数量
  80. }
  81. char buf[maxlen],ans[maxlen];
  82. string A[maxlen];
  83. int main()
  84. {
  85. int T;
  86. scanf("%d",&T);
  87. while(T--)
  88. {
  89. scanf("%d",&n);
  90. init();
  91. int ma=;
  92. for(int i=;i<n;i++)
  93. {
  94. scanf("%s",buf);
  95. int l=strlen(buf);
  96. if(ma<l)
  97. {
  98. ma=l;
  99. strcpy(ans,buf);
  100. }
  101. insert(buf,l);
  102. }
  103. build();
  104. int sum=query(ans,ma);
  105. if(sum==n) puts(ans);
  106. else puts("No");
  107. }
  108. }

AC自动机

  1. #include <stdio.h>
  2. #include <string.h>
  3. char S[];
  4. char *t[],*s;
  5. int f[];
  6. void getfail(char p[],int f[]) //字符串p自我匹配
  7. {
  8. int len=strlen(p);
  9. f[]=f[]=;
  10. for(int i=;i<len;i++)
  11. {
  12. int j=f[i];
  13. while(j&&p[i]!=p[j])
  14. j=f[j];
  15. if(p[i]==p[j])
  16. f[i+]=j+;//多匹配到了一个字符
  17. else
  18. f[i+]=;//该字符配不上
  19. }
  20. }
  21. int find(char* T, char*P, int*f)//p去匹配字符串T
  22. {
  23. int n = strlen(T), m = strlen(P);
  24. getfail(P, f); //得出部分匹配表
  25. int j = ; //短串的下标
  26. for(int i = ; i < n; i++) //长串下标
  27. {
  28. while(j && P[j] != T[i])//突然失配了
  29. {
  30. j = f[j]; //j往回退,直到0或者上一个字符相等的位置
  31. }
  32. if(P[j] == T[i])
  33. {
  34. j++; //匹配了一个字符,j++
  35. }
  36. if(j == m) //短串匹配到头了
  37. {
  38. return ;//i - m + 1;//返回成功匹配的起点字符位置
  39. }
  40. }
  41. return -;
  42. }
  43. int main()
  44. {
  45. int T,n;
  46. scanf("%d",&T);
  47. while(T--)
  48. {
  49. scanf("%d",&n);
  50. int maxlen=;
  51. int p=;//记录最长串
  52. s=S;
  53. for(int i=;i<=n;i++)
  54. {
  55. scanf("%s",s);
  56. t[i]=s;
  57. if(strlen(s)>maxlen){
  58. maxlen=strlen(s);
  59. p=i;
  60. }
  61. s+=strlen(s)+;
  62. }
  63. int ans=;
  64. for(int i=;i<=n;i++)
  65. {
  66. if(find(t[p],t[i],f)==)
  67. ans++;
  68. else break;
  69. }
  70. if(ans==n)
  71. {
  72. printf("%s\n",t[p]);
  73. }
  74. else puts("No");
  75. }
  76. return ;
  77. }

KMP

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <iostream>
  5. #define ll long long
  6. using namespace std;
  7.  
  8. int f[];
  9. int T,n;
  10. char s[];
  11. char *t[];
  12.  
  13. void getfail(char p[]) //字符串p自我匹配
  14. {
  15. int len=strlen(p);
  16. f[]=f[]=;
  17. for(int i=;i<len;i++)
  18. {
  19. int j=f[i];
  20. while(j&&p[i]!=p[j])
  21. j=f[j];
  22. if(p[i]==p[j])
  23. f[i+]=j+;//多匹配到了一个字符
  24. else
  25. f[i+]=;//该字符配不上
  26. }
  27. }
  28. int find(char* T, char*P)//p去匹配字符串T
  29. {
  30. int n = strlen(T), m = strlen(P);
  31. getfail(P); //得出部分匹配表
  32. int j = ; //短串的下标
  33. for(int i = ; i < n; i++) //长串下标
  34. {
  35. while(j && P[j] != T[i])//突然失配了
  36. {
  37. j = f[j]; //j往回退,直到0或者上一个字符相等的位置
  38. }
  39. if(P[j] == T[i])
  40. {
  41. j++; //匹配了一个字符,j++
  42. }
  43. if(j == m) //短串匹配到头了
  44. {
  45. return ;//i - m + 1;//返回成功匹配的起点字符位置
  46. }
  47. }
  48. return -;
  49. }
  50.  
  51. int main(){
  52.  
  53. int max_len;
  54. scanf("%d",&T);
  55.  
  56. while(T--){
  57. scanf("%d",&n);
  58. max_len=;
  59. int tmp;
  60. char *qw;
  61. char *io=s;
  62. for(int i= ;i <= n;i++){
  63. scanf("%s",io);
  64. tmp=strlen(io);
  65. if( tmp > max_len ){
  66. max_len=tmp;
  67. qw=io;
  68. }
  69. t[i]=io;
  70. io+=strlen(io)+;
  71. }
  72.  
  73. int flag=;
  74.  
  75. for(int j=;j<=n;j++){
  76.  
  77. if( find(qw,t[j]) != ){
  78. flag=;
  79. break ;
  80. }
  81. }
  82.  
  83. if(flag){
  84. printf("%s\n",qw);
  85. }
  86. else{
  87. printf("No\n");
  88. }
  89.  
  90. }
  91.  
  92. return ;
  93. }

another KMP

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<string>
  5. #include<vector>
  6. using namespace std;
  7.  
  8. typedef long long int LL;
  9.  
  10. int Sunday(string text, string pattern){
  11. int i = , j = , k;
  12. int m = pattern.size();
  13.  
  14. if(pattern.size() <= || text.size() <= )
  15. return -;
  16.  
  17. for(; i<text.size();) {
  18. if(text[i] != pattern[j]) {
  19. for(k=pattern.size() - ; k>=; k--) {
  20. if(pattern[k] == text[m])
  21. break;
  22. }
  23. i = m-k;
  24. j = ;
  25. m = i+pattern.size();
  26. }
  27. else {
  28. if(j == pattern.size()-)
  29. return i-j;
  30. i++;
  31. j++;
  32. }
  33.  
  34. }
  35. return -;
  36. }
  37.  
  38. vector<string> v;
  39.  
  40. int main()
  41. {
  42. ios::sync_with_stdio(false);
  43. int T;
  44. cin>>T;
  45. while(T--)
  46. {
  47. int n;
  48. cin>>n;
  49. v.clear();
  50. string t,text;
  51. for(int i=;i<n;i++)
  52. {
  53. cin>>t;
  54. if(text.length()<t.length())
  55. text=t;
  56. v.push_back(t);
  57. }
  58. int f=;
  59. for(int i=;i<n;i++)
  60. {
  61. if(Sunday(text,v[i])== -)
  62. {
  63. f=;
  64. break;
  65. }
  66. }
  67. if(f)
  68. cout<<text<<endl;
  69. else
  70. cout<<"No"<<endl;
  71. }
  72. return ;
  73. }

Sunday algorithm

HDU 6208 The Dominator of Strings【AC自动机/kmp/Sunday算法】的更多相关文章

  1. HDU 6208 The Dominator of Strings 后缀自动机

    The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java ...

  2. hdu 6208 The Dominator of Strings【AC自动机】

    hdu 6208 The Dominator of Strings[AC自动机] 求一个串包含其他所有串,找出最长串去匹配即可,但是匹配时要对走过的结点标记,不然T死QAQ,,扎心了.. #inclu ...

  3. HDU 6208 The Dominator of Strings(AC自动机)

    The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java ...

  4. HDU - 6208 The Dominator of Strings HDU - 6208 AC自动机 || 后缀自动机

    https://vjudge.net/problem/HDU-6208 首先可以知道最长那个串肯定是答案 然后,相当于用n - 1个模式串去匹配这个主串,看看有多少个能匹配. 普通kmp的话,每次都要 ...

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

    最长的才可能成为答案,那么除了最长的以外全部insert到自动机里,再拿最长的去match,如果match完以后cnt全被清空了,那么这个最长串就是答案.事实上方便起见这个最长串一起丢进去也无妨,而且 ...

  6. HDU 2222:Keywords Search(AC自动机模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2222 KMP是单模式串匹配的算法,而AC自动机是用于多模式串匹配的算法.主要由Trie和KMP的思想构成. 题意 ...

  7. SPOJ 7758. Growing Strings AC自动机DP

    Growing Strings 题目:给出n个字符串,问最多能够选出多少个串组成序列,并满足前一个字符串是后一个字符串的子串. 分析: AC自动机经典水题... 考虑每个节点结尾时,他能够选出最多的串 ...

  8. hdu_5507_GT and strings(AC自动机)

    题目链接:hdu_5507_GT and strings 题意:给n个字符串和q个询问,每个询问给两个数字x,y,问1.x是否为y的子序列,2.x是否为y的子串,是输出1,否则输出0,每个询问输出2个 ...

  9. HDU 2457/POJ 3691 DNA repair AC自动机+DP

    DNA repair Problem Description   Biologists finally invent techniques of repairing DNA that contains ...

随机推荐

  1. Codeforces数据结构(水题)小结

    最近在使用codeblock,所以就先刷一些水题上上手 使用codeblock遇到的问题 1.无法进行编译-------从setting中的编译器设置中配置编译器 2.建立cpp后无法调试------ ...

  2. BZOJ1407 [Noi2002]Savage 【扩展欧几里得】

    题目链接 BZOJ1407 题解 枚举\(m\)用扩欧判即可 #include<algorithm> #include<iostream> #include<cstrin ...

  3. 【BZOJ 1930】 [Shoi2003]pacman 吃豆豆 最大费用最大流

    如果你知道他是网络流的话你就很快会想到一个最大费用最大流的模型,然后你发现可能T,然而你发现你只用增广两次,然后你就开心的打了出来,然后发现被稠密图里spfa的丧病时间复杂度坑了,还是会T.于是我就开 ...

  4. 写一个JavaScript“返回顶部”功能

    在web页面中,如果页面较高,为了方便用户快速地返回顶部,都会添加一个返回顶部按钮. 效果演示可以查看本页.如果页面有滚动高度,右下角就会有一个含有“返回顶部”字样的黑色背景半透明的小条条.点击这里“ ...

  5. 群联MPALL(Rel) 7F V5.03.0A-DL07量产工具 PS2251-07(PS2307)

    前言:U盘被写保护,真的很醉人啊~~      群联MPALL是一款群联PS2251系列主控量产修复工具,本版本支持PS2251-67.PS2251-68.PS2251-02.PS2251-03.PS ...

  6. video视频在结束之后回到初始状态

    目前尝试了两种解决方案,但是方案1在安卓移动端无法生效(猜测是因为移动端安卓启动的是原生的视频播放控件的原因) 方案一: 重新load资源,这种方法比较简洁,但是在安卓下不适用 video.addEv ...

  7. 《vue.js实战》练习---标签页组件

    html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  8. commons

    <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang --> <dependency> <g ...

  9. Java输入输出流备忘

    重要博客: http://blog.csdn.net/hguisu/article/details/7418161 File dir = new File("\\root");   ...

  10. salt-api的使用

    curl -k https://192.168.74.129:8006/ -H "Accept: application/x-yaml" -H "X-Auth-Token ...