UVa 11107 (后缀数组 二分) Life Forms
利用height值对后缀进行分组的方法很常用,好吧,那就先记下了。
题意:
给出n个字符串,求一个长度最大的字符串使得它在超过一半的字符串中出现。
多解的话,按字典序输出全部解。
分析:
在所有输入的字符串后面加一个原串中没有的且互不相同的字符,然后将新得到的n个字符串拼接成一个长的字符串。(为什么要加互不相同的分割字符,这里始终想不明白)
首先二分最大公共字串的长度p。扫描一遍height数组,每遇到一个height[i] < p便开辟一个新段,这样就将height数组拆分为若干段。而且每一段的所有字符都有一个长度为p的公共前缀。只要某一段中包含了超过 n / 2 的原串的后缀,就满足条件了。
如何判断是否包含了某个原串的后缀,用一个flag标记数组即可实现。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = * + ; struct SuffixArray
{
int s[maxn];
int sa[maxn];
int rank[maxn];
int height[maxn];
int t[maxn], t2[maxn], c[maxn];
int n; void clear() { n = ; memset(sa, , sizeof(sa)); } void build_sa(int m)
{
int i, *x = t, *y = t2;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[i] = s[i]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= )
{
int p = ;
for(i = n - k; i < n; i++) y[p++] = i;
for(i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[y[i]]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[sa[]] = ;
for(i = ; i < n; i++)
x[sa[i]] = y[sa[i]]==y[sa[i-]] && y[sa[i]+k]==y[sa[i-]+k] ? p - : p++;
if(p >= n) break;
m = p;
}
} void build_height()
{
int i, j, k = ;
for(i = ; i < n; i++) rank[sa[i]] = i;
for(i = ; i < n; i++)
{
if(k) k--;
j = sa[rank[i] - ];
while(s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
}
}; const int maxc = + ;
const int maxl = + ;
SuffixArray sa;
int n;
char word[maxl];
int idx[maxn];
bool flag[maxc]; void print_sub(int L, int R)
{
for(int i = L; i < R; i++) printf("%c", sa.s[i] - + 'a');
puts("");
} bool good(int L, int R)
{
memset(flag, false, sizeof(flag));
int cnt = ;
for(int i = L; i < R; i++)
{
int x = idx[sa.sa[i]];
if(x != n && !flag[x]) { flag[x] = true; cnt++; }
}
return cnt > n / ;
} bool print_solution(int len, bool print)
{
int L = ;
for(int R = ; R <= sa.n; R++)
{
if(R == sa.n || sa.height[R] < len)
{
if(good(L, R))
{
if(print) print_sub(sa.sa[L], sa.sa[L] + len);
else return true;
}
L = R;
}
}
return false;
} void solve(int maxlen)
{
if(!print_solution(, false)) puts("?");
else
{
int L = , R = maxlen, M;
while(L < R)
{
M = L + (R - L + ) / ;
if(print_solution(M, false)) L = M;
else R = M - ;
}
print_solution(L, true);
}
} void add(int ch, int i)
{
idx[sa.n] = i;
sa.s[sa.n++] = ch;
} int main()
{
//freopen("in.txt", "r", stdin); int kase = ;
while(scanf("%d", &n) == && n)
{
if(kase++ > ) puts("");
sa.clear();
int maxlen = ;
for(int i = ; i < n; i++)
{
scanf("%s", word);
int sz = strlen(word);
maxlen = max(maxlen, sz);
for(int j = ; j < sz; j++) add(word[j] - 'a' + , i);
add(i + , n);
}
add(, n); sa.build_sa( + n);
sa.build_height();
solve(maxlen);
} return ;
}
代码君
UVa 11107 (后缀数组 二分) Life Forms的更多相关文章
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
- 【bzoj4310】跳蚤 后缀数组+二分
题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...
- BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)
题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...
- POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)
洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- Poj 3261 Milk Patterns(后缀数组+二分答案)
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ 3294 Life Forms(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
随机推荐
- redis cluster安装部署(测试环境)
redis 应用于web前端,做缓存和数据存取的速度是挺可观的,最近看了一些资料,手痒了,就弄了一个测试环境,两台方案,试用一下. ##Redis 集群部署## 一,方案调研: 参考博客: http: ...
- AESEncrypter加密算法代码示例
package testJava.java; import java.security.SecureRandom; import java.util.Base64; import javax.cryp ...
- Css 单图片按钮实例(css 图片变换)
1.场景描述,根据鼠标的移动,动态的切换按钮图片. 2.方法1,准备两张120*41的图片,一张正常状态图片,一张按下效果图片.在鼠标放在的按钮上设置按下图片,移开又恢复到正常状态图片.缺点:在网页上 ...
- D3D Deferred Shading
在3D图形计算中,deferred shading是一个基于屏幕空间的着色技术.之所以被称为deferred shading,是因为我们将场景的光照计算与渲染"deferred"到 ...
- URAL1018 Binary Apple Tree(树dp)
组队赛的时候的一道题,那个时候想了一下感觉dp不怎么好写呀,现在写了出来,交上去过了,但是我觉得我还是应该WA的呀,因为总感觉dp的不对. #pragma warning(disable:4996) ...
- Office 2013 note
1.每次打开重新配置: 问题表现:启动后发现每次打开都会出现“正在配置”的进度 执行:reg add HKCU\Software\Microsoft\Office\15.0\Word\Options ...
- 在wpf窗体上添加用户控件
1.引用用户控件的命名控件 xmlns:my="clr-namespace:WpfApplicationDemo.Control" 2.把用户控件添加到窗体中 <my:Use ...
- Codeforces Round #335 (Div. 2) D. Lazy Student 贪心
D. Lazy Student Student Vladislav came to his programming exam completely unprepared as usual. He ...
- JDK安装(windows/linux)
双击安装...安装之后需要进行一些相关的配置工作...下面是我自己总结的安装和配置步骤: (1)非Win7系统 第一步:安装jdk,下载地址:http://www.oracle.com/technet ...
- C# winform post请求数据
刚到公司混的时候,老板要求实现一个从C#的windows应用程序传参数到一个网页,然后这个网页不显示出来,但能把数据返回给应用程序的功能,问了好多人,找了好多资料,都搞不定,后来还是在老板的帮助下搞定 ...