poj3294 Life Forms(后缀数组)
【题目链接】
http://poj.org/problem?id=3294
【题意】
多个字符串求出现超过R次的最长公共子串。
【思路】
二分+划分height,判定一个组中是否包含不小于R个不同字符串的后缀。
需要注意的有:
1) c[]尽量开大,字符范围为“偏移”之后的范围。
2) 用kase作为标记节省了每次开始新段需要清零的时间。
3) 因为height是sa[i]与sa[i-1]的关系,所以无论是在can的开始还是在新段开始都需要初始为一个串的情况。
【代码】
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int maxn = +; int s[maxn];
int sa[maxn],c[maxn],t[maxn],t2[maxn]; void build_sa(int m,int n) {
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;
}
}
int rank[maxn],height[maxn];
void getHeight(int n) {
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[j+k]==s[i+k]) k++;
height[rank[i]]=k;
}
} int T;
char a[maxn]; int f[],kase;
vector<int> st;
int can(int limit,int n,int len) {
int cnt=,ok=;
st.clear();
f[sa[]/len]=kase;
for(int i=;i<=n;i++) {
if(height[i]<limit) {
cnt=;
f[sa[i]/len]=++kase; //检查每一个组中
}
else {
if(f[sa[i]/len]!=kase) {
f[sa[i]/len]=kase;
if(cnt>=) cnt++;
if(cnt>T/) {
ok=;
st.push_back(sa[i]);
cnt=-;
}
}
}
}
return ok;
}
void init() {
kase=;
memset(sa,,sizeof(sa));
memset(f,,sizeof(f));
}
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
while(scanf("%d",&T)== && T) {
init();
int len,n=;
for(int i=;i<T;i++) {
scanf("%s",&a);
len=strlen(a);
for(int j=;j<len;j++) s[n++]=a[j]+;
s[n++]=i+;
}
n--;
s[n]=; build_sa(,n+);
getHeight(n); int L=,R=len+;
while(L<R) {
int M=L+(R-L+)/;
if(can(M,n,len+)) L=M;
else R=M-;
}
can(L,n,len+); //再调用一次求出st
if(L==) printf("?\n");
else {
for(int i=;i<st.size();i++) {
for(int j=st[i];(j-st[i]+)<=L;j++)
printf("%c",s[j]-);
putchar('\n');
}
}
putchar('\n');
}
return ;
}
poj3294 Life Forms(后缀数组)的更多相关文章
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...
- UVA11107 Life Forms --- 后缀数组
UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- 2018.11.28 poj3294 Life Forms(后缀数组+双指针)
传送门 后缀数组经典题目. 我们先把所有的字符串都接在一起. 然后求出hththt数组和sasasa数组. 然后对于sasasa数组跑双指针统计答案. 如果双指针包括进去的属于不同字符串的数量达到了题 ...
- POJ3294 Life Forms(二分+后缀数组)
给n个字符串,求最长的多于n/2个字符串的公共子串. 依然是二分判定+height分组. 把这n个字符串连接,中间用不同字符隔开,跑后缀数组计算出height: 二分要求的子串长度,判断是否满足:he ...
随机推荐
- HTML5 ArrayBufferView之DataView
DataView视图 如果一段数据包括多种类型(比如服务器传来的HTTP数据),这时除了建立ArrayBuffer对象的复合视图以外,还可以通过DataView视图进行操作. DataView视图提供 ...
- TFS 服务器更换后工作区无法绑定
需要删除工作区,删除命令如下 tf workspace /delete 工作区名;创建的用户 /server:TFS服务器 例 tf workspace /delete WHQ-PC;whq /ser ...
- 解决右滑返回手势和UIScrollView中的手势冲突
当在一个viewController中添加了scrollView或者tableView的时候,贴边侧滑返回的时候会首先触发滚动而失效,要解决这个问题,需要通过requireGestureRecogni ...
- c# web 删除时弹出提示框
方法1: 在控件中增加属性 <asp:Button ID="btnSub" runat="server" Text="提交" oncl ...
- 封装Timer
System.Timers.Timer,System.Timers.Timer在使用的过程中需要: 1.构造函数不同,构造函数可以什么事情也不做,也可以传入响应间隔时间:System.Timers.T ...
- 那些年,我们一起被坑的H5音频
原文地址:http://weibo.com/p/23041874d6cedd0102vkbr 不要被这么文艺的标题吓到,这里不会跟你讲述中学时期泡妞史,也不会有其它什么现实不该有而小说噼里啪啦不能 ...
- Linux下定时备份数据库
linux下使用crontab定时备份MYSQL数据库的方法只需按照下面3步做,一切都在你的掌控之下: 第一步:在服务器上配置备份目录代码: mkdir /var/lib/mysqlbackup cd ...
- mysql数据类型——枚举enum(‘F’,'M')
ENUM(“value1”,“value2”,...) 说明:枚举,列值可赋予值列表中的某个成员 允许的属性:除通用属性外无其他属性 缺省值:如果列可为NULL,则为NULL:如果列为NOTNULL, ...
- VIM快捷键(转)
VIM快捷键:光标移动:四个方向 kh 0 l j ctrl+f, ctrl+b 向下翻页,向上翻页 ctrl+d, ctrl+u ...
- Day14 html简介
初识html <!DOCTYPE html> <html lang="en"> <head> <!--自闭合标签--> <me ...