题目大意:给定两个数字串,要求归并成一个且字典序最小
某奶牛题?
维护两个指针表示两个字符串各合并到了什么位置
那么这两个后缀中字典序较小者先取
用后缀数组快速比较谁字典序小
时间复杂度O((n+m)log(n+m))
又是卡时过……
《标解到底是啥系列》
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 400400
using namespace std;
int n,m;
int a[M],b[M];
int s[M],tot;
namespace Suffix_Array{
int rank[M],sa[M];
int X[M],Y[M],sum[M],temp[M],t;
void Get_Rank()
{
int i;
for(i=1;i<=tot;i++)
sum[s[i]]++;
for(i=1;i<=1001;i++)
sum[i]+=sum[i-1];
for(i=tot;i;i--)
temp[sum[s[i]]--]=i;
for(i=1;i<=tot;i++)
{
if( i==1 || s[temp[i]]!=s[temp[i-1]] )
++t;
rank[temp[i]]=t;
}
}
void Radix_Sort(int key[],int order[])
{
int i;
for(i=0;i<=tot;i++)
sum[i]=0;
for(i=1;i<=tot;i++)
sum[key[i]]++;
for(i=1;i<=tot;i++)
sum[i]+=sum[i-1];
for(i=tot;i;i--)
temp[sum[key[order[i]]]--]=order[i];
for(i=1;i<=tot;i++)
order[i]=temp[i];
}
void Prefix_Doubling()
{
int i,j;
Get_Rank();
for(j=1;j<=tot;j<<=1)
{
for(i=1;i<=tot;i++)
{
X[i]=rank[i];
Y[i]=i+j>tot?0:rank[i+j];
sa[i]=i;
}
Radix_Sort(Y,sa);
Radix_Sort(X,sa);
for(t=0,i=1;i<=tot;i++)
{
if( i==1 || X[sa[i]]!=X[sa[i-1]] || Y[sa[i]]!=Y[sa[i-1]] )
++t;
rank[sa[i]]=t;
}
}
}
}
namespace IStream{
const int L=1<<15;
char buffer[L],*S,*T;
inline char Get_Char()
{
if(S==T)
{
T=(S=buffer)+fread(buffer,1,L,stdin);
if(S==T) return EOF;
}
return *S++;
}
inline int Get_Int()
{
char c;
int re=0;
for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
while(c>='0'&&c<='9')
re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
return re;
}
}
class OStream{
private:
static const int L=1<<15;
char stack[20];int top;
char buffer[L],*S;
public:
OStream()
{
S=buffer;
}
void Put_Int(int x)
{
stack[++top]=' ';
if(!x) stack[++top]='0';
else while(x)
stack[++top]=x%10+'0',x/=10;
while(top)
{
if(S==buffer+L-1)
{
printf("%s",buffer);
S=buffer;
}
*S++=stack[top--];
}
}
~OStream()
{
*S=0;
puts(buffer);
}
}os;
int main()
{
int i;
n=IStream::Get_Int();
for(i=1;i<=n;i++)
s[++tot]=a[i]=IStream::Get_Int();
s[++tot]=1001;
m=IStream::Get_Int();
for(i=1;i<=m;i++)
s[++tot]=b[i]=IStream::Get_Int();
s[++tot]=1001;
Suffix_Array::Prefix_Doubling();
int p1=1,p2=1;
for(i=1;i<=n+m;i++)
{
if(p1==n+1)
os.Put_Int(b[p2++]);
else if(p2==m+1)
os.Put_Int(a[p1++]);
else if( Suffix_Array::rank[p1] < Suffix_Array::rank[n+1+p2] )
os.Put_Int(a[p1++]);
else
os.Put_Int(b[p2++]);
}
return 0;
}