利用height值对后缀进行分组的方法很常用,好吧,那就先记下了。

题意:

给出n个字符串,求一个长度最大的字符串使得它在超过一半的字符串中出现。

多解的话,按字典序输出全部解。

分析:

在所有输入的字符串后面加一个原串中没有的且互不相同的字符,然后将新得到的n个字符串拼接成一个长的字符串。(为什么要加互不相同的分割字符,这里始终想不明白)

首先二分最大公共字串的长度p。扫描一遍height数组,每遇到一个height[i] < p便开辟一个新段,这样就将height数组拆分为若干段。而且每一段的所有字符都有一个长度为p的公共前缀。只要某一段中包含了超过 n / 2 的原串的后缀,就满足条件了。

如何判断是否包含了某个原串的后缀,用一个flag标记数组即可实现。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5
  6 const int maxn = 1001 * 100 + 10;
  7
  8 struct SuffixArray
  9 {
 10     int s[maxn];
 11     int sa[maxn];
 12     int rank[maxn];
 13     int height[maxn];
 14     int t[maxn], t2[maxn], c[maxn];
 15     int n;
 16
 17     void clear() { n = 0; memset(sa, 0, sizeof(sa)); }
 18
 19     void build_sa(int m)
 20     {
 21         int i, *x = t, *y = t2;
 22         for(i = 0; i < m; i++) c[i] = 0;
 23         for(i = 0; i < n; i++) c[x[i] = s[i]]++;
 24         for(i = 1; i < m; i++) c[i] += c[i - 1];
 25         for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
 26         for(int k = 1; k <= n; k <<= 1)
 27         {
 28             int p = 0;
 29             for(i = n - k; i < n; i++) y[p++] = i;
 30             for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
 31             for(i = 0; i < m; i++) c[i] = 0;
 32             for(i = 0; i < n; i++) c[x[y[i]]]++;
 33             for(i = 1; i < m; i++) c[i] += c[i - 1];
 34             for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
 35             swap(x, y);
 36             p = 1; x[sa[0]] = 0;
 37             for(i = 1; i < n; i++)
 38                 x[sa[i]] = y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k] ? p - 1 : p++;
 39             if(p >= n) break;
 40             m = p;
 41         }
 42     }
 43
 44     void build_height()
 45     {
 46         int i, j, k = 0;
 47         for(i = 0; i < n; i++) rank[sa[i]] = i;
 48         for(i = 0; i < n; i++)
 49         {
 50             if(k) k--;
 51             j = sa[rank[i] - 1];
 52             while(s[i + k] == s[j + k]) k++;
 53             height[rank[i]] = k;
 54         }
 55     }
 56 };
 57
 58 const int maxc = 100 + 10;
 59 const int maxl = 1000 + 10;
 60 SuffixArray sa;
 61 int n;
 62 char word[maxl];
 63 int idx[maxn];
 64 bool flag[maxc];
 65
 66 void print_sub(int L, int R)
 67 {
 68     for(int i = L; i < R; i++) printf("%c", sa.s[i] - 1 + 'a');
 69     puts("");
 70 }
 71
 72 bool good(int L, int R)
 73 {
 74     memset(flag, false, sizeof(flag));
 75     int cnt = 0;
 76     for(int i = L; i < R; i++)
 77     {
 78         int x = idx[sa.sa[i]];
 79         if(x != n && !flag[x]) { flag[x]  = true; cnt++; }
 80     }
 81     return cnt > n / 2;
 82 }
 83
 84 bool print_solution(int len, bool print)
 85 {
 86     int L = 0;
 87     for(int R = 1; R <= sa.n; R++)
 88     {
 89         if(R == sa.n || sa.height[R] < len)
 90         {
 91             if(good(L, R))
 92             {
 93                 if(print) print_sub(sa.sa[L], sa.sa[L] + len);
 94                 else return true;
 95             }
 96             L = R;
 97         }
 98     }
 99     return false;
100 }
101
102 void solve(int maxlen)
103 {
104     if(!print_solution(1, false)) puts("?");
105     else
106     {
107         int L = 1, R = maxlen, M;
108         while(L < R)
109         {
110             M = L + (R - L + 1) / 2;
111             if(print_solution(M, false)) L = M;
112             else R = M - 1;
113         }
114         print_solution(L, true);
115     }
116 }
117
118 void add(int ch, int i)
119 {
120     idx[sa.n] = i;
121     sa.s[sa.n++] = ch;
122 }
123
124 int main()
125 {
126     //freopen("in.txt", "r", stdin);
127
128     int kase = 0;
129     while(scanf("%d", &n) == 1 && n)
130     {
131         if(kase++ > 0) puts("");
132         sa.clear();
133         int maxlen = 0;
134         for(int i = 0; i < n; i++)
135         {
136             scanf("%s", word);
137             int sz = strlen(word);
138             maxlen = max(maxlen, sz);
139             for(int j = 0; j < sz; j++) add(word[j] - 'a' + 1, i);
140             add(i + 100, n);
141         }
142         add(0, n);
143
144         sa.build_sa(100 + n);
145         sa.build_height();
146         solve(maxlen);
147     }
148
149     return 0;
150 }

代码君

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4442030.html

UVa 11107 (后缀数组 二分) Life Forms相关推荐

  1. HDU - 5030 Rabbit's String(后缀数组+二分)

    题目链接:点击查看 题目大意:给出一个字符串,现在要求将其分为不大于k个连续的子串,对于每个子串求出字典序最大的子串,现在要求所有子串的最大子串的最大值最小,输出这个最大子串 题目分析:最大值最小,标 ...

  2. HDU - 5008 Boring String Problem(后缀数组+二分)

    题目链接:点击查看 题目大意:给出一个字符串,接下来给出 q 个询问,每次询问字符串中第 k 大的子串,要求输出该字串的左右端点,如果有多个答案,输出左端点最小的一个 题目分析:因为在求出后缀数组后, ...

  3. bzoj3277 串 (后缀数组+二分答案+ST表)

    常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...

  4. SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)

    [题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...

  5. 洛谷 P4094 [HEOI2016/TJOI2016]字符串 后缀数组+二分+主席树

    题目链接 后缀数组 题目分析: sa[i] – 第i小的后缀的编号 rank[i] --编号为i的后缀排第几: height[i] – 第i和第i-1的最长lcp最长公共前缀: 1.二分答案,答案肯定 ...

  6. [BZOJ4310]跳蚤-后缀数组-二分答案

    跳蚤 Description 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究.首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择 ...

  7. POJ - 1226 Substrings(后缀数组+二分)

    题目链接:点击查看 题目大意:给出n个字符串,求出n个字符串中或者在他们翻转过来的字符串中,出现的最长公共子串的长度 题目分析:说白了就是求n个字符串中的最长公共子串的变形,而这个变形也相当简单,只是 ...

  8. BZOJ3998 TJOI2015弦论(后缀数组+二分答案)

    先看t=1的情况.显然得求出SA(因为我不会SAM).我们一位位地确定答案.设填到了第len位,二分这一位填什么之后,在已经确定的答案所在的范围(SA上的某段区间)内二分,找到最后一个小于当前串的后缀 ...

  9. Musical Theme POJ - 1743(后缀数组+二分)

    求不可重叠最长重复子串 对于height[i]定义为sa[i]和 sa[i-1]的最长公共前缀 这个最长公共前缀的值肯定是最大的 证明: 设rank[j] < rank[k], 则不难证明后缀j ...

最新文章

  1. Android开发--多媒体应用开发(一)--MediaPlayer的使用介绍
  2. STL源码剖析---STL容器特征总结(含迭代器失效)
  3. 【数据结构与算法】之深入解析“打家劫舍II”的求解思路与算法示例
  4. 基础知识回顾——异常处理
  5. 关于java中求和的方法,用可变变量来解决这个问题
  6. 深度学习 | MATLAB卷积神经网络原理描述
  7. GIS软件开发入门需要学习哪些内容?
  8. HART转PROFIBUS DP(V0)+RS485方法
  9. HUSTOJ配置文件解释
  10. HTML 教程-菜鸟教程
  11. King Arthur's Knights 【HDU - 4337】【哈密顿回路性质Dirac定理】
  12. 谈谈如何做到从未来看向当代的能源技术
  13. ICE java实现helloworld
  14. 【C++]参数的缺省值
  15. 人生如逆旅,我亦是行人
  16. css 好看滚动条样式大全,CSS 个性化滚动条样式
  17. 65W氮化镓Switch底座扩展坞方案
  18. Matlab中num2str函数的用法
  19. 密度峰值聚类算法介绍(DPC)
  20. Naked dog come out

热门文章

  1. GitLab安装后修改IP/域名
  2. python中的日志操作和发送邮件
  3. 试用SpringBoot创建WEB应用
  4. 鼠标滚轮 控制作用滚动
  5. AppCompat 22.1,Google暴走,MD全面兼容低版本
  6. 高档名片设计:12款专业的名片设计欣赏
  7. File not found 错误 nginx
  8. 转:python模块学习 ---- smtplib 邮件发送
  9. 各种操作系统ping时的TTL值
  10. [踏月独行]一生能有多少爱