4278: [ONTAK2015]Tasowanie 后缀数组+贪心

用SA快速判断后缀的字典序大小然后贪心。
233yzy神犇掉一句话慢了10倍。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 400005
using namespace std;
int n,m,len;
int cc[N],sa[N],rank[N],t1[N],t2[N],s[N];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool cmp(int *y,int a,int b,int k)
{
    int arank1=y[a];
    int brank1=y[b];
    int arank2=a+k>=len?-1:y[a+k];
    int brank2=b+k>=len?-1:y[b+k];
    return arank1==brank1&&arank2==brank2;
}
inline void make_sa()
{
    int *x=t1,*y=t2;
    int m=1005;
    for (int i=0;i<m;i++) cc[i]=0;
    for (int i=0;i<len;i++) ++cc[x[i]=s[i]];
    for (int i=1;i<m;i++) cc[i]+=cc[i-1];
    for (int i=len-1;~i;i--)  sa[--cc[x[i]]]=i;
    for (int k=1;k<len;k<<=1)
    {
        int p=0;
        for (int i=len-k;i<len;i++) y[p++]=i;
        for (int i=0;i<len;i++)
            if (sa[i]>=k) y[p++]=sa[i]-k;
        for (int i=0;i<m;i++) cc[i]=0;
        for (int i=0;i<len;i++) ++cc[x[y[i]]];
        for (int i=1;i<m;i++) cc[i]+=cc[i-1];
        for (int i=len-1;~i;i--) sa[--cc[x[y[i]]]]=y[i];
        swap(x,y); m=1; x[sa[0]]=0;
        for (int i=1;i<len;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?m-1:m++;
        if (m>=len) break;
    }
}
inline void print(int x)
{
    if (!x) putchar('0');
    else
    {
        char s[22]; int top=0;
        while (x) s[++top]=x%10+'0',x/=10;
        while (top) putchar(s[top--]);
    }
    putchar(32);
}   
int main()
{
    n=read();
    for (int i=0;i<n;i++) s[i]=read();
    s[n]=1001;
    m=read();
    for (int i=1;i<=m;i++) s[n+i]=read();
    len=n+m+1;
    make_sa();
    for (int i=0;i<len;i++) rank[sa[i]]=i;
    int top1=0,top2=0;
    while (top1<n||top2<m)
    {
        if (top1==n) 
            for (;top2<m;top2++) print(s[top2+n+1]);
        else if (top2==m)
            for (;top1<n;top1++) print(s[top1]);
        else
        {
            if (rank[top1]<rank[top2+n+1]) print(s[top1++]);
            else print(s[(top2++)+n+1]);
        }
    }
    return 0;
}

你可能感兴趣的:(4278: [ONTAK2015]Tasowanie 后缀数组+贪心)