传送门

后缀数组经典题目。

我们先把所有的字符串都接在一起。

然后求出hththt数组和sasasa数组。

然后对于sasasa数组跑双指针统计答案。

如果双指针包括进去的属于不同字符串的数量达到了题目给出的限制我们就更新答案并不断右移左指针。

如果没有达到限制就一直右移右指针。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<algorithm>
#define ri register int
using namespace std;
const int N=2e5+5;
int rk[N],sa[N],sa2[N],ht[N],n,m,len[N],tt,tot[N],st[N][18],Log[N],idx[N];
char s[N],t[N];
vector<int>ans;
inline void Sort(){
	static int cnt[N];
	for(ri i=1;i<=m;++i)cnt[i]=0;
	for(ri i=1;i<=n;++i)++cnt[rk[i]];
	for(ri i=2;i<=m;++i)cnt[i]+=cnt[i-1];
	for(ri i=n;i;--i)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void getsa(){
	for(ri i=1;i<=n;++i)rk[i]=(int)s[i],sa2[i]=i;
	m=122,Sort();
	for(ri w=1,p=0;m^n;w<<=1,p=0){
		for(ri i=n-w+1;i<=n;++i)sa2[++p]=i;
		for(ri i=1;i<=n;++i)if(sa[i]>w)sa2[++p]=sa[i]-w;
		Sort(),swap(sa2,rk),rk[sa[1]]=p=1;
		for(ri i=2;i<=n;++i)rk[sa[i]]=(sa2[sa[i]]==sa2[sa[i-1]]&&sa2[sa[i]+w]==sa2[sa[i-1]+w])?p:++p;
		m=p;
	}
	for(ri i=1,j,k=0;i<=n;ht[rk[i++]]=k)for(k?--k:k,j=sa[rk[i]-1];s[i+k]==s[j+k];++k);
	for(ri i=1;i<=n;++i)st[i][0]=ht[i];
	for(ri j=1;j<=17;++j)for(ri i=1;i+(1<<j)<=n;++i)st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
inline int rmq(int l,int r){return min(st[l][Log[r-l+1]],st[r-(1<<Log[r-l+1])+1][Log[r-l+1]]);}
inline bool check(int a,int b,int len){
	a=rk[a],b=rk[b];
	if(a>b)a^=b,b^=a,a^=b;
	return rmq(a+1,b)<len;
}
inline void solve(){
	ri sig=0,mxlen=0,lim=(tt>>1)+1,l=tt,r=tt-1;
	ans.clear();
	for(int i=1;i<=tt;++i)tot[i]=0;
	for(;;++l){
		while(sig<lim&&r<len[tt]){
			++r,++tot[idx[sa[r]]];
			if(tot[idx[sa[r]]]==1)++sig;
		}
		if(sig^lim)break;
		while(sig==lim){
			--tot[idx[sa[l]]];
			if(!tot[idx[sa[l]]]){
				ri tmp=rmq(l+1,r);
				if(tmp){
					if(tmp>mxlen)ans.clear(),ans.push_back(sa[l]),mxlen=tmp;
					else if(tmp==mxlen)ans.push_back(sa[l]);
				}
				--sig;
				break;
			}
			++l;
		}
	}
	if(!mxlen)puts("?");
	else for(ri i=0;i<ans.size();++i)if(!i||check(ans[i],ans[i-1],mxlen)){for(ri j=ans[i],k=1;k<=mxlen;++k,++j)cout<<s[j];puts("");}
}
int main(){
	freopen("lx.in","r",stdin);
	freopen("owon.out","w",stdout);
	Log[0]=-1;
	for(ri i=1;i<=200000;++i)Log[i]=Log[i>>1]+1;
	while(scanf("%d",&tt),n=0,tt){
		for(ri i=1;i<=tt;++i){
			scanf("%s",t),len[i]=strlen(t),s[++n]=(char)i;
			for(ri j=0;j<len[i];++j)s[++n]=t[j];
			++len[i],len[i]+=len[i-1];
		}
		for(ri i=1;i<=tt;++i)for(ri j=len[i-1]+1;j<=len[i];++j)idx[j]=i;
		getsa();
		solve(),puts("");
	}
	return 0;
}

2018.11.28 poj3294 Life Forms(后缀数组+双指针)的更多相关文章

  1. POJ3294 Life Forms —— 后缀数组 最长公共子串

    题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total ...

  2. POJ3294 Life Forms(后缀数组)

    引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...

  3. 2018.11.24 poj3261Milk Patterns(后缀数组)

    传送门 后缀数组经典题. 貌似可以用二分答案+后缀数组? 我自己yyyyyy了一个好写一点的方法. 直接先预处理出heightheightheight数组. 然后对于所有连续的k−1k-1k−1个he ...

  4. 2018.11.24 poj3415Common Substrings(后缀数组+单调栈)

    传送门 常数实在压不下来(蒟蒻开O(3)都过不了). 但有正确性233. 首先肯定得把两个字符串接在一起. 相当于heightheightheight数组被height<kheight<k ...

  5. UVA11107 Life Forms --- 后缀数组

    UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...

  6. Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

    题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...

  7. 2016vijos 1-1 兔子的字符串(后缀数组 + 二分 + 哈希)

    题意: 给出一个字符串,至多将其划分为n部分,每一部分取出字典序最大的子串ci,最小化 最大的ci 先看一个简化版的问题: 给一个串s,再给一个s的子串t,问能否通过将串划分为k个部分,使t成为划分后 ...

  8. POJ 3294 UVA 11107 Life Forms 后缀数组

    相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...

  9. POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串

                                                                              Life Forms Time Limit: 500 ...

随机推荐

  1. Python 学习笔记---爬取海贼王动漫

    最近无聊整理的爬虫代码,可以自动爬取腾讯动漫的任意漫画,思路如下: 1. 先获取想下载的动漫url, 这里用了 getUrls ,直接获取动漫的最后一章 2. 然后进入到该动漫去获取要下载的图片url ...

  2. TOJ 4383 n % ( pow( p , 2) ) ===0

    传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4383 描述 There is a ...

  3. 100-days: Six

    Title: School lessons (be) to cover sexting, FGM and mental health(精神健康) be to do sth 将要做某事  =>  ...

  4. f5故障排除

    1.硬件问题 1)硬盘:查看/var/log/daemon, kern日志,smartctl测试,EUD 2)PSU: 查看LCD报警,/var/log/ltm,EUD等 3)内存:可能导致设备突然重 ...

  5. 【Linux 进程】exec族函数详解

    exec族的组成: 在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是: #include <unistd.h> extern char **e ...

  6. python之集合【set】

    初学python,今天晚上学习了set,做下set的总结,set的中文名也就是[集合],set的总结分为两部分,第一部分是set的创建,第二部分是set的操作,也就是set的功能:set的特点是无序的 ...

  7. jmeter简单压测设置

    参数化 随机参数 时间参数 顺序自增函数  文件读取  直接引用 响应断言 用来查看sessionid 关联 关联引用 jmeter操作数据库 安装连接程序包 ip 端口号 哪个数据库 可以执行多条s ...

  8. Nginx中超时时间配置(转)

    本文介绍 Nginx 的 超时(timeout)配置.分享给大家,具体如下: Nginx 处理的每个请求均有相应的超时设置.如果做好这些超时时间的限定,判定超时后资源被释放,用来处理其他的请求,以此提 ...

  9. mysql 5.6 datetime 保存精确到秒

    mysql中的CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP 设置默认值 now(3)  datetime 长度  3   保存精确到秒

  10. day 12 内置函数,装饰器,递归函数

    内置函数 内置函数:python给咱们提供了一些他认为你会经常用到的函数,68种      内置函数     abs() dict() help() min() setattr() all()  di ...