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

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

    因为每次要放后缀较小的那个,所以把两个序列放在一起排序吧。改一改模板。

    其实要改的地方就是让后面序列那部分不要在倍增的时候更新前面序列那部分。

    考虑 4 和 43 ,应该是 43 比 4 小;因为放了单独的 4 的话就只能放 43 ,而放了 43 的 4 的话可以放 3 再放单独的 4 。

      即,前缀相等的话短的比较大、长的比较小。把 n-k+1 ~ n 的那个赋值放在 if( sa[i] > k ) 的赋值后面就行了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=4e5+5;
    int n,m,tn,a[N],sa[N],tp[N],rk[N],tx[N];
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    void Rsort(int nm)
    {
      for(int i=1;i<=nm;i++)tx[i]=0;
      for(int i=1;i<=tn;i++)tx[rk[i]]++;
      for(int i=2;i<=nm;i++)tx[i]+=tx[i-1];
      for(int i=tn;i;i--)sa[tx[rk[tp[i]]]--]=tp[i];
    }
    void work()
    {
      int nm=1000;
      for(int i=1;i<=tn;i++)tp[i]=i,rk[i]=a[i];
      Rsort(nm);
      for(int k=1;k<=tn;k<<=1)
        {
          int tot=0;
          for(int i=1,j=n+k;i<=tn;i++)
        if((sa[i]<=n&&sa[i]>k)||(sa[i]>j))
          tp[++tot]=sa[i]-k;
          for(int i=max(1,n-k+1);i<=n;i++)tp[++tot]=i;//max//here after ...
          for(int i=max(n+1,tn-k+1);i<=tn;i++)tp[++tot]=i;
          Rsort(nm);
          swap(rk,tp);nm=1;rk[sa[1]]=1;
          for(int i=2,u,v;i<=tn;i++)
        {
          u=sa[i]+k;v=sa[i-1]+k;
          if((sa[i]<=n&&u>n)||(sa[i]>n&&u>tn))u=0;
          if((sa[i-1]<=n&&v>n)||(sa[i-1]>n&&v>tn))v=0;
          rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[u]==tp[v])?nm:++nm;//rk[sa[i]]
        }
          if(nm==tn)break;
        }
    }
    int main()
    {
      n=rdn();for(int i=1;i<=n;i++)a[i]=rdn();
      m=rdn();tn=n+m;for(int i=n+1;i<=tn;i++)a[i]=rdn();
      work();
      int p0=1,p1=n+1;
      for(int i=1;i<=tn;i++)
        {
          if(rk[p0]<rk[p1])printf("%d ",a[p0]),p0++;
          else printf("%d ",a[p1]),p1++;
          if(p0>n||p1>tn)break;
        }
      if(p0<=n)for(;p0<=n;p0++)printf("%d ",a[p0]);
      if(p1<=tn)for(;p1<=tn;p1++)printf("%d ",a[p1]);
      puts("");
      return 0;
    }
  • 相关阅读:
    WPF 打开文件 打开路径对话框
    WPF Button添加图片
    Delphi 正则表达式PerlRegEx
    解决Inet控件下载utf8网页乱码的问题
    Delphi程序结构
    VB 936(gb2312)URL编码与解码
    Chr 将一个有序数据转换为一个ANSI字符
    Delphi正则表达式使用方法(TPerlRegEx)
    Delphi类型转换
    Delphi 正则表达式TPerlRegEx 类的属性与方法
  • 原文地址:https://www.cnblogs.com/Narh/p/10075775.html
Copyright © 2011-2022 走看看