zoukankan      html  css  js  c++  java
  • bzoj 4278 Tasowanie —— 后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4278

    每次取两个后缀中字典序较小的那个的首字符;

    注意超出去的部分是 inf 而不是 0,因为如果到了比较超出去部分的时候,那就是一个串走到了末尾而另一个没有(或者都到末尾,不过都到末尾就随便选啦),而且两个后缀的 LCP 顶到了末尾;

    这时选长度较长的比较优,因为反正 LCP 处一样,先选较短的等选完以后还是得过来,不如先选较长的,也许后面还出现更优的。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const xn=4e5+5;
    int n,m,mx,a[xn>>1],b[xn>>1],s[xn],tp[xn],sa[xn],rk[xn],tax[xn];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void Rsort()
    {
      int len=n+m;
      for(int i=1;i<=mx;i++)tax[i]=0;
      for(int i=1;i<=len;i++)tax[rk[tp[i]]]++;
      for(int i=1;i<=mx;i++)tax[i]+=tax[i-1];
      for(int i=len;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];
    }
    int ps(int nw,int k)
    {
      if(nw<=n&&nw+k>n)return 0;
      return nw+k;
    }
    void work()
    {
      int len=n+m;
      for(int i=1;i<=len;i++)rk[i]=s[i],tp[i]=i;
      Rsort(); int up=max(n,m);
      for(int k=1;k<=up;k<<=1)
        {
          int num=0;
          //for(int i=len-k+1;i<=len;i++)tp[++num]=i;
          //for(int i=n-k+1;i<=n;i++)tp[++num]=i;
          for(int i=1;i<=len;i++)
        if((sa[i]<=n&&sa[i]>k)||(sa[i]>n&&sa[i]>n+k))tp[++num]=sa[i]-k;
          for(int i=len-k+1;i<=len;i++)tp[++num]=i;
          for(int i=n-k+1;i<=n;i++)tp[++num]=i;
          Rsort(); swap(rk,tp);
          rk[sa[1]]=1; num=1;
          for(int i=2;i<=len;i++)
        rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[ps(sa[i],k)]==tp[ps(sa[i-1],k)])?num:++num;
          if(num==len)break;
          mx=num;
        }
    }
    int main()
    {
      n=rd(); for(int i=1;i<=n;i++)a[i]=rd(),s[i]=a[i],mx=max(mx,a[i]);
      m=rd(); for(int i=1;i<=m;i++)b[i]=rd(),s[n+i]=b[i],mx=max(mx,b[i]);
      work();
      int p1=1,p2=1;
      while(p1<=n&&p2<=m)
        {
          if(rk[p1]<rk[n+p2])printf("%d ",a[p1++]);
          else printf("%d ",b[p2++]);
        }
      if(p1>n)while(p2<=m)printf("%d ",b[p2++]);
      if(p2>m)while(p1<=n)printf("%d ",a[p1++]);
      puts("");
      return 0;
    }
  • 相关阅读:
    JSP中Session的使用
    深入了解父类引用指向子类
    Gamma校正及其OpenCV实现
    cocos2d-x3.0之请求网络(phpserver)
    Quartz使用-入门使用(java定时任务实现)
    ExtJs--15--Ext.is*各种类型推断的方法,简单看源代码就能够明确了
    小谈边界问题
    VS2010旗舰版安装图解
    LSPCI具体解释分析
    兔子--gradle安装和配置
  • 原文地址:https://www.cnblogs.com/Zinn/p/10075772.html
Copyright © 2011-2022 走看看