POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话:
将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组。然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中。这个做法的时间复杂度为O(nlogn)。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdlib> using namespace std;
const int N = 110008;
int wa[N],wb[N],wv[N],ws0[N];
int val[N], sum[N], tp1[N], tp2[N];
int sa[N], rank[N], height[N];
int hs[N]; char tp[1008];
int str[N];
bool vis[1000]; vector<int> v; int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws0[i]=0;
for(i=0;i<n;i++) ws0[x[i]=r[i]]++;
for(i=1;i<m;i++) ws0[i]+=ws0[i-1];
for(i=n-1;i>=0;i--) sa[--ws0[x[i]]]=i;
for(j=1,p=1;p<n;j*=2,m=p)
{
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws0[i]=0;
for(i=0;i<n;i++) ws0[wv[i]]++;
for(i=1;i<m;i++) ws0[i]+=ws0[i-1];
for(i=n-1;i>=0;i--) sa[--ws0[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
return;
}
void calheight(int *r,int *sa,int n)
{
int i,j,k=0;
for(i=1;i<=n;i++) rank[sa[i]]=i;
for(i=0;i<n;height[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
return;
} bool check(int m, int n, int num){
memset(vis , 0, sizeof(vis));
int cnt = 0;
int size = 0;
for(int i = 1; i <= n ;i++){
if(height[i] >= m){//分组,同组内计数
if(!vis[hs[ sa[i] ]]){
cnt++;
vis[hs[ sa[i] ]] = 1;
} if(!vis[hs[ sa[i - 1] ]]){//不同组
cnt++;
vis[hs[ sa[i - 1] ]] = 1;
} }else{
if(cnt > num){
if(size == 0){
v.clear();
}
size++;
v.push_back(sa[i - 1]);
}
cnt = 0;
memset(vis, 0 , sizeof(vis)); }
}
if(size){
return true;
}else{
return false;
} } int main(){
int k;
bool flag = 0;
while(~scanf("%d", &k ) && k){
v.clear();
int n = 0;
int mini = 100000000;
for(int t = 0; t < k; t++){
scanf("%s", tp);
int len = strlen(tp);
mini = min(mini, len);
for(int i = n, j = 0; j < len; i++, j++){
str[i] = tp[j];
hs[i] = t;
}
n += len + 1;
if(t != k - 1){
str[n - 1] = t + 130;
}
}
n--;
str[n] = 0;
da(str, sa , n + 1 , 256);
calheight(str, sa, n);
int l = 1, r = mini;
int ans = 0;
while(l <= r){
int m = (l + r)>>1;
if(check(m, n, k / 2 )){
l = m + 1;
ans = m;
}else{
r = m - 1;
}
}
if(flag){
printf("\n");
}
flag = 1;
if(ans){
for(int i = 0; i < v.size(); i++){
int st = v[i];
for(int j = 0; j < ans; j++){
printf("%c", str[st + j]);
}
printf("\n");
}
}else{
printf("?\n");
} }
return 0;
}
POJ3294 Life Forms(后缀数组)的更多相关文章
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- 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 ...
随机推荐
- 在Navicat for MySQL中打开视图时,提示视图没有主键的问题
一直把视图理解为一个select语句而已,视图一般就是用于查询,不会通过视图来更新表或视图本身的数据,所以视图根本不需要什么主键.今天自己建了一个视图view_test: drop view if e ...
- JavaScript——事件模型
DOM事件流: DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程可称为DOM事件 ...
- mybatis Result Maps collection already contains value for com.ebways.dictionary.dao.impl.PtInfoDaoImpl.beanMap
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.conte ...
- 如何在maven中添加本地jar包
mvn install:install-file -DgroupId=mytest-DartifactId=test-Dversion=1.1 -Dpackaging=jar -Dfile=d:\te ...
- Unity3d NavMesh获得地面高度
UnityPro内置的NavMesh有几个API很有用 NavMesh.SamplePosition 根据给的点进行采样,可传入最大距离,返回true说明采样到了点,否则采样失败(可以用来获得地形高度 ...
- ios iphone6 Plus 的适配问题
最近更新一个老程序,发现在iphone6 plus上用nslog打印出的screen 的frame还是320*568, 不是414*736, 查了一下,原来需要设置iphone6 plus的启动画面才 ...
- linux资源使用配置文件 /etc/security/limits.conf和ulimit
limits.conf文件实际上是linux PAM中pam_limits.so的配置文件,而且只针对于单个会话. limits.conf的格式如下: <domain> <type& ...
- windows.h和winsock2.h包含顺序问题(转)
windows.h和winsock2.h有类型重定义我是知道的,本来就一个库来说没问题,把winsock2放到windows.h前或先定义WIN32_LEAN_AND_MEAN都能解决问题但现的出了问 ...
- GIT简单操作
以下只是简单的bash的操作命令,个人比较喜欢用gui 打开 git bash here git clone https://github.com/自己的名字/trunk git checkout + ...
- Effective C++ -----条款37:绝不重新定义继承而来的缺省参数值
绝对不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而virtual函数-----你唯一应该覆写的东西-----却是动态绑定.