poj 3294 Life Forms【SA+二分】
先加入未出现字符间隔把n个串连起来,注意如果串开的char这个间隔字符不能溢出,把这个接起来的串跑SA,二分答案k,判断的时候把连续一段he>=k的分成一组,然后看着一段是否包含了>n/2的串的后缀。
统计是否出现这里可以用时间戳优化visit数组,就不用每次memset了
输出答案的时候和二分判断一样,找到合法的子串就输出
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200005;
int m,n,wa[N],wb[N],wv[N],wsu[N],sa[N],rk[N],he[N],v[N],ti,de,bl[N];
char s[N],t[N];
bool cmp(int r[],int a,int b,int l)
{
	return r[a]==r[b]&&r[a+l]==r[b+l];
}
void saa(char r[],int n,int m)
{
	int *x=wa,*y=wb;
	for(int i=0;i<=m;i++)
		wsu[i]=0;
	for(int i=1;i<=n;i++)
		wsu[x[i]=r[i]]++;
	for(int i=1;i<=m;i++)
		wsu[i]+=wsu[i-1];
	for(int i=n;i>=1;i--)
		sa[wsu[x[i]]--]=i;
	for(int j=1,p=1;j<n&&p<n;j<<=1,m=p)
	{
		p=0;
		for(int i=n-j+1;i<=n;i++)
			y[++p]=i;
		for(int i=1;i<=n;i++)
			if(sa[i]>j)
				y[++p]=sa[i]-j;
		for(int i=1;i<=n;i++)
			wv[i]=x[y[i]];
		for(int i=0;i<=m;i++)
			wsu[i]=0;
		for(int i=1;i<=n;i++)
			wsu[wv[i]]++;
		for(int i=1;i<=m;i++)
			wsu[i]+=wsu[i-1];
		for(int i=n;i>=1;i--)
			sa[wsu[wv[i]]--]=y[i];
		swap(x,y);
		p=1;
		x[sa[1]]=1;
		for(int i=2;i<=n;i++)
			x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
	}
	for(int i=1;i<=n;i++)
		rk[sa[i]]=i;
	for(int i=1,j,k=0;i<=n;he[rk[i++]]=k)
		for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
}
bool ok(int w)
{
	for(int i=2,la;i<=n;i=la+1)
	{
		la=i;
		ti++;
		int sm=0;
		v[bl[sa[la-1]]]=ti,sm++;
		while(he[la]>=w)
		{
			if(v[bl[sa[la]]]!=ti)
				v[bl[sa[la]]]=ti,sm++;
			la++;
		}//cerr<<i<<" "<<la<<"   "<<sm<<endl;
		if(sm>m/2)
			return 1;
	}
	return 0;
}
int main()
{
	while(scanf("%d",&m)&&m)
	{
		n=0,de=26;
		for(int j=1;j<=m;j++)
		{
			scanf("%s",t+1);
			for(int i=1,len=strlen(t+1);i<=len;i++)
				s[++n]=t[i]-'a',bl[n]=j;
			s[++n]=++de,bl[n]=j;
		}
		saa(s,n,200);
		int l=0,r=1000,ans=0;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(ok(mid))
				l=mid+1,ans=mid;
			else
				r=mid-1;
		}//cerr<<ans<<endl;
		if(ans==0)
		{
			puts("?\n");
			continue;
		}
		for(int i=2,la;i<=n;i=la+1)
		{
			la=i;
			ti++;
			int sm=0;
			v[bl[sa[la-1]]]=ti,sm++;
			while(he[la]>=ans)
			{
				if(v[bl[sa[la]]]!=ti)
					v[bl[sa[la]]]=ti,sm++;
				la++;
			}
			if(sm>m/2)
			{
				for(int j=0;j<ans;j++)
					if(s[sa[i]+j]<=26)
						printf("%c",s[sa[i]+j]+'a');
				puts("");
			}
		}
		puts("");
	}
	return 0;
}
poj 3294 Life Forms【SA+二分】的更多相关文章
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
		题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ... 
- POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]
		题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submiss ... 
- POJ 3294 Life Forms(后缀数组+二分答案)
		[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ... 
- poj 3294 Life Forms - 后缀数组 - 二分答案
		题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ... 
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
		Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ... 
- 字符串(后缀数组):POJ 3294 Life Forms
		Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, d ... 
- poj 3294 Life Forms
		后缀数组的题目,把后缀连接起来,这个还是先二分答案,然后选取一段连续的height值,判断这些height代表的后缀有没有覆盖一半以上的字符串. 得出答案的长度之后还要在枚举连续的heigh,判断有没 ... 
- poj 3294 Life Forms(后缀数组)
		题意:给你最多100个字符串,求最长的且是一半以上的字符串的公共子串,如果有多个,按字典序输出. 思路:先把各个串拼起来,中间加上一个之前未出现过的字符,然后求后缀.然后根据h数组和sa数组,求出最长 ... 
- POJ 3294 n个串中至少一半的串共享的最长公共子串
		Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12484 Accepted: 3502 Descr ... 
随机推荐
- python—networkx:依据图的权重绘图
			首先输入边和边的权重,随后画出节点位置.依据权重大小划分实边和虚边 #coding:utf-8 #!/usr/bin/env python """ An example ... 
- TCP 的那些事儿(下)(转)
			TCP的RTT算法 从前面的TCP的重传机制我们知道Timeout的设置对于重传非常重要, 设长了,重发就慢,没有效率,性能差: 设短了,重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多 ... 
- JNI——访问数组
			JNI在处理基本类型数组和对象数组上面是不同的.对象数组里面是一些指向对象实例或者其它数组的引用. 因为速度的原因,先通过GetXXXArrayElements函数把简单类型的数组转化成本地类型的数组 ... 
- javascript 复制粘贴操作
			function CopyCode(key){ var trElements = document.all.tags("tr");//获取tr元素 var i; for(i = 0 ... 
- 判断IPv6地址合法性
			在 <netinet/in.h> 头文件下有下列这些宏用于判断IPv6地址合法性 返回0代表true,返回非零值代表ipv6地址为非指定类型的的地址(false) int IN6_IS_A ... 
- 项目Beta冲刺(团队3/7)
			项目Beta冲刺(团队3/7) 团队名称: 云打印 作业要求: 项目Beta冲刺(团队) 作业目标: 完成项目Beta版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 陈宇 ... 
- UR#34. 多项式乘法
			#34. 多项式乘法 统计 描述 提交 自定义测试 这是一道模板题. 给你两个多项式,请输出乘起来后的多项式. 输入格式 第一行两个整数 nn 和 mm,分别表示两个多项式的次数. 第二行 n+1n+ ... 
- 记一次OGG数据写入HBase的丢失数据原因分析
			一.现象二.原因排查2.1 SparkStreaming程序排查2.2 Kafka数据验证2.3 查看OGG源码2.3.1 生成Kafka消息类2.3.2 Kafka配置类2.3.3 Kafka 消息 ... 
- YTU 2456: 评委打分
			2456: 评委打分 时间限制: 1 Sec 内存限制: 128 MB 提交: 283 解决: 52 题目描述 一个歌唱比赛,比赛每次会从观众中随即抽取几名观众给分(观众至少有5个,分数为0~1 ... 
- 从OutStreamWriter 和Filewriter谈Java编码
			首先看JAVA API的描述: ABOUT OutputStreamWriter: "An OutputStreamWriter is a bridge from character str ... 
