zoukankan      html  css  js  c++  java
  • UVA 11107 Life Forms

    https://vjudge.net/problem/UVA-11107

    题目

    给n个字符串,每个字符串只由小写字母构成,求所有长度最长、在大于n/2个字符串中出现的字符串。如果有多个,按照字典序输出。

    1<=n<=100,每个字符串不超过1000个字母。

    时限6666ms

    题解

    不会做,书上提示用比较大的字符把这些字符串连接起来,然后求后缀数组和height数组,然后二分最大长度,将height>二分长度份的段,O(n)判断一下有多少种字符串,然后得到答案,时间复杂度O(nlogn)

    然后问如何使用栈来做,然后我就按照栈来做了,写了很久,发现又慢又难写……大部分都是60ms AC,我交上去是70ms

    可能是用了bitset才特别慢,但是我不想改了……

    类似于单调栈,当遇到小于前一个height的时候,弹栈并计算字符串出现次数。由于出现的字符串编号是乱的,需要使用长度为100的bitset来统计

    对height=0的后缀,只管弹栈,把这个编号放进下一个后缀,甚至可以所有后缀的编号都放进下一个后缀

    然后就是慢慢调了

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<bitset>
    using namespace std;
    #define MAXN 107
    unsigned char s[MAXN*1000], id[MAXN*1000];
    int sa[MAXN*1000], t1[MAXN*1000], t2[MAXN*1000], c[MAXN*1000], l, m;
    int rk[MAXN*1000], height[MAXN*1000], hid[MAXN*1000];
    inline void calcsa() {
    	int *x=t1, *y=t2;
    	int now=0;
    	for(int i=0; i<m; i++) c[i]=0;
    	for(int i=0; i<l; i++) c[x[i]=s[i]-'a']++;
    	for(int i=1; i<m; i++) c[i]+=c[i-1];
    	for(int i=l-1; i>=0; i--) sa[--c[x[i]]]=i;
    	for(int k=1; k<=l; k<<=1) {
    		int p=0;
    		for(int i=l-k; i<l; i++) y[p++]=i;
    		for(int i=0; i<l; i++) if(sa[i]>=k) y[p++]=sa[i]-k;
    
    		for(int i=0; i<m; i++) c[i]=0;
    		for(int i=0; i<l; i++) c[x[y[i]]]++;
    		for(int i=1; i<m; i++) c[i]+=c[i-1];
    
    		for(int i=l-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i];
    		swap(x,y);
    		p=1; x[sa[0]]=0;
    		for(int i=1; i<l; i++) {
    			x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
    		}
    		if(p>=l) break;
    		m=p;
    	}
    	for(int i=0; i<l; i++) rk[i]=x[i];
    	for(int i=0; i<l; i++) {
    		if(s[i]>'z') now=s[i]-'z';
    		id[i]=now;
    	}
    	for(int i=0, k=0; i<l; i++) if(rk[i]) {
    		if(k) k--;
    		int j=sa[rk[i]-1];
    		while(i+k<l && j+k<l && s[i+k]==s[j+k]) k++;
    		height[rk[i]]=k;
    	}
    	for(int i=0; i<l; i++) {
    		hid[i]=id[sa[i]];
    	}
    }
    inline void putsn(char *s, int n) {
    	while(0<n--) putchar((*(s++)));
    	putchar('
    ');
    }
    int sth[MAXN*1000], sz, stk[MAXN*1000];
    bitset<100> stb[MAXN*1000], now;
    
    int n, ch=0, flg[MAXN*1000];
    inline void solve_stack() {
    
    	sz=0; //sth[0]=l+7; stb[0].reset(); stb[0].set(hid[0]);
    	int ans=-1; bool ok=false;
    	height[l]=0;
    	for(int i=0; i<=l; i++) {
    //		printf("*%d %d %d=%s", sa[i], hid[i], height[i], s+sa[i]);
    		int ht=0x3f3f3f3f;
    		now.reset();
    		if(sz>0) {
    			int kk=stk[sz-1];
    			while(sz>0 && sth[sz-1]>height[i]) {
    				if(ht<0x3f3f3f3f && ht>height[i]) {
    					now.set(hid[stk[sz-1]]);
    					if(now.count()>n/2) break;
    				}
    				now|=stb[sz-1];
    
    				ht=min(ht,sth[--sz]);
    			}
    			while(sz>0 && sth[sz-1]>height[i]) sz--;
    			int nans=now.count();
    			if(nans>n/2) {
    				ok=true;
    				nans=ht;
    				if(nans>ans) {
    					ans=nans, flg[kk]=++ch;
    				} else if(nans==ans) {
    					flg[kk]=ch;
    				}
    			}
    		}
    //		printf("	%d
    ", now.count());
    		if(height[i]>0) {
    			sth[sz]=height[i];
    			now.set(hid[i-1]); now.set(hid[i]);
    			stb[sz]=now;
    			stk[sz]=i;
    			sz++;
    		}
    	}
    	if(ok) {
    		for(int i=1; i<l; i++) if(flg[i]==ch) {
    			putsn((char*)s+sa[i], ans);
    		}
    	} else puts("?");
    }
    int main() {
    	bool fi=false;
    	memset(flg,-1,sizeof flg);
    	while(~scanf("%d", &n) && n) {
    		if(fi) putchar('
    '); else fi=true;
    		char *p=(char*) s;
    		m=26+n;
    		for(int i=0; i<n; i++) {
    			scanf("%s", p);
    			int l=strlen(p);
    			p+=l;
    			*p=(unsigned)'z'+1+i;
    			p++;
    		}
    		if(n==1) {*(--p)=0; puts((char*)s);continue;}
    		*p=0;
    		l=strlen((char*) s);
    		calcsa();
    		solve_stack();
    	}
    }
    
  • 相关阅读:
    Shiro理解与总结
    spark教程(14)-共享变量
    Hive 教程(十)-UDF
    multivariate_normal 多元正态分布
    windows 安装 python 踩坑记录
    EM 算法(三)-GMM
    EM 算法(二)-KMeans
    EM 算法(一)-原理
    sklearn-GDBT
    集成学习-Boosting 模型深度串讲
  • 原文地址:https://www.cnblogs.com/sahdsg/p/13347511.html
Copyright © 2011-2022 走看看