zoukankan      html  css  js  c++  java
  • bzoj 4278 [ONTAK2015]Tasowanie

    给出两个字符串 A B 让我们对其二路归并 求出能够归并出的最小字典序。

    考虑后缀数组 不难发现我们将B直接连在A上会出现问题 问题是 A串剩下的和B串完全相同了 那么此时比大小就会用到B的部分 这是不合理的。

    考虑怎么解决这个问题 如果比到了末尾之后的数字 那么较长的串答案不会更差 所以考虑在中间加一个INF.

    对于B也有这种情况 那么需要在末尾也加一个INF 即可解决问题 可以证明这样做是最优的。

    具体的 可以这样思考 我们之所以让较长的优先 是考虑到了较长的第一个决定字典序的位置上的字符 其如果比当前参与比较的都大 那么不管优不优先对结果没有影响 反之必然更优。

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 10000000000000000ll
    #define ld long double
    #define pb push_back
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1);
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define pii pair<int,int> 
    #define F first
    #define S second
    #define mk make_pair
    #define P 13331ll
    #define mod 1000003
    #define RE register
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;char ch=getc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    	return x*f;
    }
    const int MAXN=200010<<2;
    int n1,n2,n,m;
    int a[MAXN],sa[MAXN],rk[MAXN],x[MAXN],y[MAXN],c[MAXN];
    inline void SA()
    {
    	m=1001;
    	rep(1,n,i)++c[x[i]=a[i]];
    	rep(1,m,i)c[i]+=c[i-1];
    	fep(n,1,i)sa[c[x[i]]--]=i;
    	for(int k=1;k<=n;k=k<<1)
    	{
    		int num=0;
    		rep(n-k+1,n,i)y[++num]=i;
    		rep(1,n,i)if(sa[i]>k)y[++num]=sa[i]-k;
    		rep(1,m,i)c[i]=0;
    		rep(1,n,i)++c[x[i]];
    		rep(1,m,i)c[i]+=c[i-1];
    		fep(n,1,i)sa[c[x[y[i]]]--]=y[i];
    		rep(1,n,i)y[i]=x[i],x[i]=0;
    		x[sa[1]]=num=1;
    		rep(2,n,i)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?num:++num;
    		if(num==n)break;
    		m=num;
    	}
    	rep(1,n,i)rk[sa[i]]=i;
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n1);
    	rep(1,n1,i)get(a[i]);
    	a[n1+1]=1001;
    	get(n2);
    	rep(1,n2,i)get(a[n1+1+i]);
    	n=n1+1+n2+1;a[n]=1001;
    	SA();
    	int i=1,j=n1+2,w=n1+n2;
    	while(w)
    	{
    		if(j>=n||rk[i]<rk[j])printf("%d ",a[i]),++i;
    		else printf("%d ",a[j]),++j;
    		--w;
    	}
    	return 0;
    }
    
  • 相关阅读:
    JDBC MySQL 实例之 用户管理系统
    利用JDBC连接数据库(MySQL)
    CSS01
    HTML01
    GUI编程02
    GUI编程01
    名词解释
    Navicat MySQL安装
    Eclipse安装Web/JavaEE插件、Eclipse编写HTML代码
    Pascal输出星星
  • 原文地址:https://www.cnblogs.com/chdy/p/12583987.html
Copyright © 2011-2022 走看看