【bzoj4278】 [ONTAK2015]Tasowanie 后缀数组

怎么开始刷水了?

并起来,加个大数,求个后缀数组比较排名就可以了。

为什么这个题行末还要有空格呀?明明样例没有的。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 400010 

using namespace std;

int a[maxn];
int wa[maxn],wb[maxn],wc[maxn],sa[maxn],rank[maxn];
int n,m,len1,len2;

void get_sa()
{
	int *x=wa,*y=wc,*t;
	for (int i=0;i<=m;i++) wb[i]=0;
	for (int i=1;i<=n;i++) wb[x[i]=a[i]]++;
	for (int i=1;i<=m;i++) wb[i]+=wb[i-1];
	for (int i=n;i>=1;i--) sa[wb[x[i]]--]=i;
	for (int j=1,p=1;p<n;j*=2,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=0;i<=m;i++) wb[i]=0;
		for (int i=1;i<=n;i++) wb[x[y[i]]]++;
		for (int i=1;i<=m;i++) wb[i]+=wb[i-1];
		for (int i=n;i>=1;i--) sa[wb[x[y[i]]]--]=y[i];
		t=x;x=y;y=t;
		p=1;x[sa[1]]=1;
		for (int i=2;i<=n;i++)
		  if (y[sa[i]]==y[sa[i-1]] && y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p;
		  else x[sa[i]]=++p;
	}
}

int main()
{
	scanf("%d",&len1);
	for (int i=1;i<=len1;i++) scanf("%d",&a[i]);
	a[len1+1]=1001;
	scanf("%d",&len2);
	for (int i=1;i<=len2;i++) scanf("%d",&a[len1+i+1]);
	n=len1+len2+1;m=1001;
	get_sa();
	for (int i=1;i<=n;i++) rank[sa[i]]=i;
	int i=1,j=1;
	while (i<=len1 || j<=len2)
	{
		if (i<=len1 && j<=len2)
		{
			if (rank[i]<rank[len1+1+j]) printf("%d",a[i++]);
			else printf("%d",a[len1+1+(j++)]);
		}
		else if (i<=len1) printf("%d",a[i++]);
		else printf("%d",a[len1+1+(j++)]);
		printf(" ");
	}
	printf("\n");
	return 0;
}


你可能感兴趣的:(【bzoj4278】 [ONTAK2015]Tasowanie 后缀数组)