题意:给你N个串,求一个串在大于等于N/2的模板串中连续出现。如果有多解按字典序最小输出。

白书模板题。二分答案+合并模板串成一个新串,扫秒新串的height数组。

考查后缀数组+LCP

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5.  
  6. const int maxn = * + ;
  7.  
  8. struct SuffixArray
  9. {
  10. int s[maxn]; // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0)
  11. int sa[maxn]; // 后缀数组
  12. int rank[maxn]; // 名次数组. rank[0]一定是n-1,即最后一个字符
  13. int height[maxn]; // height数组
  14. int t[maxn], t2[maxn], c[maxn]; // 辅助数组
  15. int n; // 字符个数
  16.  
  17. void clear()
  18. {
  19. n = ;
  20. memset(sa, , sizeof(sa));
  21. }
  22.  
  23. // m为最大字符值加1。调用之前需设置好s和n
  24. void build_sa(int m)
  25. {
  26. int i, *x = t, *y = t2;
  27. for(i = ; i < m; i++) c[i] = ;
  28. for(i = ; i < n; i++) c[x[i] = s[i]]++;
  29. for(i = ; i < m; i++) c[i] += c[i-];
  30. for(i = n-; i >= ; i--) sa[--c[x[i]]] = i;
  31. for(int k = ; k <= n; k <<= )
  32. {
  33. int p = ;
  34. for(i = n-k; i < n; i++) y[p++] = i;
  35. for(i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
  36. for(i = ; i < m; i++) c[i] = ;
  37. for(i = ; i < n; i++) c[x[y[i]]]++;
  38. for(i = ; i < m; i++) c[i] += c[i-];
  39. for(i = n-; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
  40. swap(x, y);
  41. p = ;
  42. x[sa[]] = ;
  43. for(i = ; i < n; i++)
  44. x[sa[i]] = y[sa[i-]]==y[sa[i]] && y[sa[i-]+k]==y[sa[i]+k] ? p- : p++;
  45. if(p >= n) break;
  46. m = p;
  47. }
  48. }
  49.  
  50. void build_height()
  51. {
  52. int i, j, k = ;
  53. for(i = ; i < n; i++) rank[sa[i]] = i;
  54. for(i = ; i < n; i++)
  55. {
  56. if(k) k--;
  57. int j = sa[rank[i]-];
  58. while(s[i+k] == s[j+k]) k++;
  59. height[rank[i]] = k;
  60. }
  61. }
  62. };
  63.  
  64. const int maxc = + ; // 串的个数
  65. const int maxl = + ; // 每个串的长度
  66.  
  67. SuffixArray sa;
  68. int n;
  69. char word[maxl];
  70. int idx[maxn];
  71. int flag[maxc];
  72.  
  73. // 子串[L,R) 是否符合要求
  74. bool good(int L, int R)
  75. {
  76. memset(flag, , sizeof(flag));
  77. if(R - L <= n/) return false;
  78. int cnt = ;
  79. for(int i = L; i < R; i++)
  80. {
  81. int x = idx[sa.sa[i]];
  82. if(x != n && !flag[x])
  83. {
  84. flag[x] = ;
  85. cnt++;
  86. }
  87. }
  88. return cnt > n/;
  89. }
  90.  
  91. void print_sub(int L, int R)
  92. {
  93. for(int i = L; i < R; i++)
  94. printf("%c", sa.s[i] - + 'a');
  95. printf("\n");
  96. }
  97.  
  98. bool print_solutions(int len, bool print)
  99. {
  100. int L = ;
  101. for(int R = ; R <= sa.n; R++)
  102. {
  103. if(R == sa.n || sa.height[R] < len) // 新开一段
  104. {
  105. if(good(L, R))
  106. {
  107. if(print) print_sub(sa.sa[L], sa.sa[L] + len);
  108. else
  109. return true;
  110. }
  111. L = R;
  112. }
  113. }
  114. return false;
  115. }
  116.  
  117. void solve(int maxlen)
  118. {
  119. if(!print_solutions(, false))
  120. printf("?\n");
  121. else
  122. {
  123. int L = , R = maxlen, M;
  124. while(L < R)
  125. {
  126. M = L + (R-L+)/;
  127. if(print_solutions(M, false)) L = M;
  128. else R = M-;
  129. }
  130. print_solutions(L, true);
  131. }
  132. }
  133.  
  134. // 给字符串加上一个字符,属于字符串i
  135. void add(int ch, int i)
  136. {
  137. idx[sa.n] = i;
  138. sa.s[sa.n++] = ch;
  139. }
  140.  
  141. int main()
  142. {
  143. int kase = ;
  144. while(scanf("%d", &n) == && n)
  145. {
  146. if(kase++ > ) printf("\n");
  147. int maxlen = ;
  148. sa.clear();
  149. for(int i = ; i < n; i++)
  150. {
  151. scanf("%s", word);
  152. int sz = strlen(word);
  153. maxlen = max(maxlen, sz);
  154. for(int j = ; j < sz; j++)
  155. add(word[j] - 'a' + , i);
  156. add( + i, n); // 结束字符
  157. }
  158. add(, n);
  159.  
  160. if(n == ) printf("%s\n", word);
  161. else
  162. {
  163. sa.build_sa( + n);
  164. sa.build_height();
  165. solve(maxlen);
  166. }
  167. }
  168. return ;
  169. }

uva 11107 Life Forms的更多相关文章

  1. 后缀数组LCP + 二分 - UVa 11107 Life Forms

    Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...

  2. 后缀数组 UVA 11107 Life Forms

    题目链接 题意:训练指南P223 分析:二分长度,把所有字符串连成一个字符串,中间用不同的字符分隔(这是为了保证匹配长度始终在一个字符串内).height数组分段,vis数组标记哪些字符串被访问了,如 ...

  3. UVA - 11107 Life Forms (广义后缀自动机)

    题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 对这n个字符串建广义后缀自动机,建完后每个字符串在自动机上跑一遍,沿fail树向上更新所有子串结点的出现次数( ...

  4. POJ 3294 UVA 11107 Life Forms 后缀数组

    相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...

  5. UVA - 11107 Life Forms (广义后缀自动机+后缀树/后缀数组+尺取)

    题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 这道题算是我的一个黑历史了吧,以前我的做法是对这n个字符串建广义后缀自动机,然后在自动机上dfs,交上去AC了 ...

  6. UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)

    题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...

  7. UVa 11107 (后缀数组 二分) Life Forms

    利用height值对后缀进行分组的方法很常用,好吧,那就先记下了. 题意: 给出n个字符串,求一个长度最大的字符串使得它在超过一半的字符串中出现. 多解的话,按字典序输出全部解. 分析: 在所有输入的 ...

  8. UVA - 11107:Life Forms

    后缀数组height+二分 #include<cstdio> #include<cstdlib> #include<algorithm> #include<c ...

  9. UVA 11107(Life Forms-后缀数组+二分)

    Problem C: Life Forms You may have wondered why most extraterrestrial life forms resemble humans, di ...

随机推荐

  1. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

  2. VB逆向

    大家或许有所察觉了,随着我们课程的不断深入学习,我们感觉自身逆向的“内功”也在不断的增进! 我们从爆破入手,到现在逐步大家进入程序的内部,认识不同编译器开发的程序,探索不同的加密逻辑. 前边,我们的例 ...

  3. printf在终端输出时改变颜色

    在调试程序时,有时候要输出大量数据,如果让printf/fprintf改变输出数据的颜色,那观察数据就方便多了. 终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关.转义序 ...

  4. 一个HexToInt的C/C++函数

    int  BetterVenca25(char* hex){   int res=0;   for(;*hex;hex++)   {  int d=toupper(*hex);      if(d & ...

  5. hdu 4035 Maze 概率DP

        题意:    有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,    从结点1出发,开始走,在每个结点i都有3种可能:        1.被杀死,回到结点1处(概率为ki)      ...

  6. Redis hash数据类型操作

    Redis hash是一个string类型的field和value的映射表.一个key可对应多个field,一个field对应一个value.将一个对象存储 为hash类型,较于每个字段都存储成str ...

  7. java内存模型分析2

    不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成,线程.主内存和工作内存的交互关系如下图所示,和上图很类似. 这里的主内存.工作内存与Java内存区域的Java堆. ...

  8. mybatis传入map参数parameterType

    基本数据类型:包含int,String,Date等.基本数据类型作为传参,只能传入一个.通过#{参数名} 即可获取传入的值 复杂数据类型:包含JAVA实体类.Map.通过#{属性名}或#{map的Ke ...

  9. QDialog之屏蔽Esc键(过滤,或者丢弃)

    http://blog.csdn.net/u011012932/article/details/50357323

  10. MS SQL SERVER: msdb.dbo.MSdatatype_mappings & msdb.dbo.sysdatatypemappings

    --SQL转Oracle/DB2的类型对应关系SELECT *FROM msdb.dbo.MSdatatype_mappings; --MS SQL SERVER更详细得显示了ORACLE/DB2各个 ...