Poj3294 Life Forms

题目传送门

哈哈哈广义SAM真的好简(du)单(liu)啊

到时候讲课可以拿来祸害众生,Yeah!

好了开始讲题解,我们将所有字符串加入广义SAM里面

对每一个节点维护一个bitset表示它在哪些主串中出现过,让后标记上传就用或运算就好了

因为题目要求输出方案,加上一个dfs就可以了,复杂度O(L*n/64)

(其实题目本质就是parent树上每个节点为一个集合,求一个子树的并的大小而已,金牌之王zjt给出了一种更优秀的做法,每次将具有相同元素的节点按照dfs序排好,让后在相邻两个节点的lca上面做上标记-1,标记节点操作可以在构建广义SAM的时候就可以完成,求lca可以用树剖,这样复杂度就是O(L lg L),不过鉴于此题n<=100,上面bitset做法会更快)

当然,这道题也是SA的经典题,不过还是广义SAM比较好看~

#include<bitset>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 350010
using namespace std;
char c[N];
bitset<110> sz[N];
int s[N][26],mx[N],f[N],ans=0;
int n,m,lst=1,cnt=1,v[N],r[N];
inline int extend(int c){
	int p=lst,np=lst=++cnt,q,nq;
	mx[np]=mx[p]+1;
	for(;p&&!s[p][c];p=f[p]) s[p][c]=np;
	if(!p) return f[np]=1;
	q=s[p][c];
	if(mx[q]==mx[p]+1) f[np]=q;
	else{
		nq=++cnt;
		mx[nq]=mx[p]+1;
		f[nq]=f[q]; f[q]=f[np]=nq;
		memcpy(s[nq],s[q],26<<2);
		for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq;
	}
}
inline void Ex_extend(int c){
	int p=lst,q=s[p][c],nq;
	if(q){
		if(mx[p]+1==mx[q]) lst=q;
		else{
			lst=nq=++cnt;
			mx[nq]=mx[p]+1;
			f[nq]=f[q]; f[q]=nq;
			memcpy(s[nq],s[q],26<<2);
			for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq;
		}
	} else extend(c);
	sz[lst][m]=1;
}
inline void dfs(int x,int d){
	if(d!=mx[x] || d>ans) return;
	if(mx[x]==ans && sz[x].count()>m){ puts(c); return; }
	for(int i=0;i<26;++i)
		if(s[x][i]){ c[d]=i+'a'; dfs(s[x][i],d+1); c[d]=0; }
}
inline void init(){
	memset(s,0,sizeof s); 
	memset(f,0,sizeof f);
	memset(v,0,sizeof v);
	ans=0;
	for(;cnt;--cnt) sz[cnt]=0;
	cnt=1;
}
int _18520(){ init();
	scanf("%d",&n); if(!n) return 0;
	for(m=0;m<n;++m){
		scanf("%s",c); lst=1;
		for(int i=0,l=strlen(c);i<l;++i) Ex_extend(c[i]-'a');
	} m=n>>1; memset(c,0,sizeof c);
	for(int i=1;i<=cnt;++i) ++v[mx[i]];
	for(int i=1;i<=cnt;++i) v[i]+=v[i-1];
	for(int i=cnt;i;--i) r[v[mx[i]]--]=i;
	for(int p,i=cnt;i;--i){
		p=r[i]; sz[f[p]]|=sz[p];
		if(sz[p].count()>m) ans=max(ans,mx[p]);
	}
	if(!ans) puts("?"); else dfs(1,0); puts(""); return 1;
} 
int main(){ while(_18520()); }
posted @ 2017-11-30 17:35  扩展的灰(Extended_Ash)  阅读(153)  评论(0编辑  收藏  举报