传送门

后缀数组经典题目。

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

然后求出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. echarts折线图Demo

    echarts链接:http://echarts.baidu.com/examples/editor.html?c=line-stack 黑底代码:http://gallery.echartsjs.c ...

  2. idea不识别yml配置文件,怎么办?

      问题描述: 如下图,新建的springboot项目,添加了自定义的配置文件后,2.yml无法像上方文件的一样,被识别成配置文件! 虽然可能不会影响项目(不确定),但问题不解决,根本没有心情开始下一 ...

  3. Word打开时显示*模板*,删除模板

    XP系统, 找到目录 C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates 删除里面的模板文件即可

  4. windows核心编程

    第一章 函数返回值: void:不可能失败.极少数会返回VOID BOOL:失败返回0 HANDLE:失败会返回NULL 或INVALID_HANDLE_VALUE PVOID:失败返回NULL wa ...

  5. JFinal Web开发学习(四)数据库连接与自动生成model

    1.新建数据库jfinal_test,user表 /* Navicat MySQL Data Transfer Source Server : . Source Server Version : 50 ...

  6. 微信网页JS分享,微信二次分享无缩略图问题

    很多时候我们要在微信中分享h5网页,这个时候就得用微信的分享接口来自定义分享的地址.标题.描述.缩略图了. 分享到微信的时候遇到一个问题,就是第一次分享到微信里,是正确的,但是在微信打开分享的链接,再 ...

  7. vue项目网站换肤

    由于我网站不是的单色,换动的样式有点多,所以我只能通过后端传给我的不同的皮肤类型,来控制不同的样式文件 在网上查了一堆,每一个有用的 if(store.getters.infoType==1){ re ...

  8. JAVA虚拟机是?为什么称作是“平台无关的语言”?

    Java虚拟机(Java Virtual Machine)简称JVM ,它是抽象化的计算机,有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.JVM屏蔽了与具体操作系统平台相关的信 ...

  9. u-boot之怎么实现分区

    启动参数bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0中kernel在哪定义,为什么可以直接引用?针对这个问题展开思考最终定位到 ...

  10. hdu 4717(三分) The Moving Points

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4717 n个点,给出初始坐标和移动的速度和移动的方向,求在哪一时刻任意两点之间的距离的最大值的最小. 对于最 ...