码迷,mamicode.com
首页 > 其他好文 > 详细

[xsy1260]短信加密

时间:2018-03-28 12:22:27      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:char s   har   mem   ems   时间   sort   开始   scanf   +=   

技术分享图片

比较朴素的想法就是枚举子串的长度$l$并找到最大的$k$,这样做是$O(n^3)$的

我们可以用后缀数组优化这个过程,同样是枚举$l$,只不过我们可以把所有后缀按$height\geq l$的连续段分组,先扫一遍找出所有长度$\geq l$的出现多次的子串,然后按$sa$排序,贪心地从前往后取,看最大能取到的$k$是什么,就做完了

快排估计会超时,所以这里我们可以用计数排序做到$O(n^2)$的总时间复杂度

p.s.说实话一开始被$n=10^4$吓到了,但实际上这个平方不是满的,又有$\text{2s}$时限,所以不虚==

#include<stdio.h>
#include<string.h>
struct pr{
	int c[2],id;
	pr(int a=0,int b=0,int d=0){c[0]=a;c[1]=b;id=d;}
}p[16010],q[16010];
bool operator!=(pr a,pr b){return a.c[0]!=b.c[0]||a.c[1]!=b.c[1];}
int rk[32010],sa[16010],h[16010],c[16010],n;
int max(int a,int b){return a>b?a:b;}
void sort(int n,int f){
	int i,m;
	memset(c,0,sizeof(c));
	m=0;
	for(i=1;i<=n;i++){
		m=max(m,p[i].c[f]);
		c[p[i].c[f]]++;
	}
	for(i=1;i<=m;i++)c[i]+=c[i-1];
	for(i=n;i>0;i--)q[c[p[i].c[f]]--]=p[i];
	for(i=1;i<=n;i++)p[i]=q[i];
}
char s[16010];
void suf(){
	int i,l,m;
	for(i=1;i<=n;i++)rk[i]=s[i];
	for(l=1;l<=n;l<<=1){
		for(i=1;i<=n;i++)p[i]=pr(rk[i],rk[i+l],i);
		sort(n,1);
		sort(n,0);
		m=0;
		for(i=1;i<=n;i++){
			if(p[i]!=p[i-1])m++;
			rk[p[i].id]=m;
		}
	}
	for(i=1;i<=n;i++)sa[rk[i]]=i;
	l=0;
	for(i=1;i<=n;i++){
		if(l)l--;
		while(s[i+l]==s[sa[rk[i]-1]+l])l++;
		h[rk[i]]=l;
	}
}
int main(){
	int las,i,l,k,L,K,M,ans;
	scanf("%s",s+1);
	n=strlen(s+1);
	suf();
	L=K=ans=0;
	for(l=1;l<=n/2;l++){
		memset(c,0,sizeof(c));
		M=1;
		for(i=2;i<=n;i++){
			if(h[i]>=l)
				c[sa[i-1]]=c[sa[i]]=M;
			else
				M++;
		}
		M=0;
		for(i=1;i<=n;i++){
			if(c[i]){
				M++;
				p[M]=pr(c[i],i);
			}
		}
		sort(M,1);
		sort(M,0);
		las=p[1].c[1];
		k=1;
		p[M+1].c[0]=0;
		for(i=2;i<=M+1;i++){
			if(p[i].c[0]!=p[i-1].c[0]){
				if(k*l>K*L){
					K=k;
					L=l;
					ans=las;
				}
				k=1;
				las=p[i].c[1];
			}else if(las+l<=p[i].c[1]){
				k++;
				las=p[i].c[1];
			}
		}
	}
	if(ans==0){
		puts("-1");
		return 0;
	}
	printf("%d\n",L*K);
	for(i=ans;i<ans+L;i++)putchar(s[i]);
}

[xsy1260]短信加密

标签:char s   har   mem   ems   时间   sort   开始   scanf   +=   

原文地址:https://www.cnblogs.com/jefflyy/p/8662666.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!