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 ...
随机推荐
- ActionResult 常见问题
1:在Asp.net Mvc 2中由于对数据的保护,当返回类型为JsonResult时 ,默认情况下request需要为post.(可使用 return Json(person,JsonReque ...
- ASP.NET Excel数据导入数据库
<identity impersonate="true"/> 是指模拟IIS身份验证 導入錯誤時可刪除 protected void btnImport_Click(o ...
- SGU 276 Andrew's Troubles
简单的题.直接找题意来就好了. #include <iostream> #include <cstdio> using namespace std; int s, n, ans ...
- WHU 1568 Product (DP、逆元)
题意: 定义f(x) 为数x的所有数字的乘积. 求满足f(k)=f(x)的不同的不含数字1的k的个数. x的长度小于50. 不超过1000组数据. Solution: 由于函数是乘积的形式,可以由质因 ...
- 【POJ2886】【线段树】Who Gets the Most Candies?
Description N children are sitting in a circle to play a game. The children are numbered from 1 to N ...
- win7访问windows server 2003服务器出现未知的用户名或者错误的密码(转载)
直接放答案,感谢网友提供答案,否则自已还一直在纳闷,为什么? win7系统的安全机制限制了登陆.只要系统时间和win2003服务器的系统时间相差很多,系统就会阻止其登陆,并显示错误信息:"未 ...
- MySql数据库3【优化4】连接设置的优化
1.wait_timeout / interactive_timeout 连接超时 服务器关闭连接之前等待活动的秒数.MySQL所支持的最大连接数是有限的,因为每个连接的建立都会消耗内存,因此我们希 ...
- UFLDL实验报告2:Sparse Autoencoder
Sparse Autoencoder稀疏自编码器实验报告 1.Sparse Autoencoder稀疏自编码器实验描述 自编码神经网络是一种无监督学习算法,它使用了反向传播算法,并让目标值等于输入值, ...
- oracle常见为题汇总,以及一个简单数据连接操作工厂
本人软件环境:win8.1 64位操作系统,vs2013,安装好了与oracle数据库对应的客户端 连接oracle数据库.以及操作数据库 1.使用IIS建立网站,浏览网页时候,提示“ ...
- C语言陷阱——类型转换
以下例子取自<深入理解计算机系统>. 考虑如下的C语言代码: #include<stdio.h> typedef unsigned char* byte_pointer; vo ...