• [NOI2015][BZOJ4199] 品酒大会|后缀数组|并查集


    八中并没有题面……

    后缀数组

    即lcp(i,j)=l的后缀对的数量及w[i]*w[j]的最大值。

    按height从大到小处理,把相邻的合并到一起,并查集维护。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<algorithm>
      6 #include<cmath>
      7 #define inf 1ll<<62
      8 #define ll long long
      9 #define N 300005
     10 using namespace std;
     11 char s[N];
     12 int len,w[N];
     13 int fa[N],size[N],list[N],max_val[N],min_val[N];
     14 int sa[N],rank[N],height[N],t1[N],t2[N],cc[N];
     15 ll ans[2][N];
     16 inline int read()
     17 {
     18     int a=0,f=1; char c=getchar();
     19     while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
     20     while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
     21     return a*f;
     22 }
     23 inline bool cmp(int x,int y)
     24 {
     25     return height[x]==height[y]?x>y:height[x]>height[y];
     26 }
     27 inline bool cmp0(int *y,int a,int b,int k)
     28 {
     29     int arank1=y[a];
     30     int brank1=y[b];
     31     int arank2=a+k>=len?-1:y[a+k];
     32     int brank2=b+k>=len?-1:y[b+k];
     33     return arank1==brank1&&arank2==brank2;
     34 }
     35 inline void make_sa()
     36 {
     37     int m=256;
     38     int *x=t1,*y=t2;
     39     for (int i=0;i<m;i++) cc[i]=0;
     40     for (int i=0;i<len;i++) ++cc[x[i]=s[i]];
     41     for (int i=1;i<m;i++) cc[i]+=cc[i-1];
     42     for (int i=len-1;i>=0;i--) sa[--cc[x[i]]]=i;
     43     for (int k=1;k<len;k<<=1)
     44     {
     45         int p=0;
     46         for (int i=len-k;i<len;i++) y[p++]=i;
     47         for (int i=0;i<len;i++)
     48             if (sa[i]>=k) y[p++]=sa[i]-k;
     49         for (int i=0;i<m;i++) cc[i]=0;
     50         for (int i=0;i<len;i++) ++cc[x[y[i]]];
     51         for (int i=1;i<m;i++) cc[i]+=cc[i-1];
     52         for (int i=len-1;i>=0;i--) sa[--cc[x[y[i]]]]=y[i];
     53         swap(x,y);
     54         m=1; x[sa[0]]=0;
     55         for (int i=1;i<len;i++)
     56             x[sa[i]]=cmp0(y,sa[i-1],sa[i],k)?m-1:m++;
     57         if (m>=len) break;
     58     }
     59 }
     60 inline void make_height()
     61 {
     62     for (int i=0;i<len;i++) rank[sa[i]]=i;
     63     int k=0; height[0]=0;
     64     for (int i=0;i<len;i++)
     65     {
     66         if (!rank[i]) continue;
     67         int j=sa[rank[i]-1];
     68         if (k) k--;
     69         while (s[i+k]==s[j+k]) k++;
     70         height[rank[i]]=k;
     71     }
     72 }
     73 int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
     74  
     75 inline void merge(int x,int y)
     76 {
     77     size[y]+=size[x];
     78     max_val[y]=max(max_val[y],max_val[x]);
     79     min_val[y]=min(min_val[y],min_val[x]);
     80     fa[x]=y;
     81 }
     82 int main()
     83 {
     84     len=read(); 
     85     scanf("%s",s);
     86     for (int i=0;i<len;i++) w[i]=read();
     87     make_sa();
     88     make_height();
     89     for (int i=0;i<len;i++)
     90     {
     91         max_val[i]=min_val[i]=w[sa[i]];
     92         fa[i]=i;
     93         size[i]=1;
     94         list[i]=i;
     95         ans[1][i]=-inf;
     96     }
     97     sort(list,list+len,cmp);
     98    
     99     for (int i=0;i<len-1;i++)
    100     {
    101         int x=find(list[i]-1),y=find(list[i]);
    102         ans[0][height[list[i]]]+=1ll*size[x]*size[y];
    103         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1ll*max_val[x]*max_val[y]);
    104         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1ll*max_val[x]*min_val[y]);
    105         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1ll*min_val[x]*max_val[y]);
    106         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1ll*min_val[x]*min_val[y]);
    107         merge(x,y);
    108     }
    109     for (int i=len-2;i>=0;i--) ans[0][i]+=ans[0][i+1],ans[1][i]=max(ans[1][i],ans[1][i+1]);
    110     for (int i=0;i<len;i++) printf("%lld %lld
    ",ans[0][i],ans[0][i]?ans[1][i]:0);
    111     return 0;
    112 }
  • 相关阅读:
    delphi 常用的将窗口置前的函数
    delphi中Message消息的使用方法
    批处理 删除文件
    CDR话单主要字段介绍
    集成学习算法总结----Boosting和Bagging
    Benchmark简介
    脚本中export不起作用的原因分析
    RAID详解[RAID0/RAID1/RAID10/RAID5]
    基于DPI(深度报文解析)的应用识别
    DPI (Deep Packet Inspection) 深度包检测技术
  • 原文地址:https://www.cnblogs.com/ws-fqk/p/4751222.html
Copyright © 2020-2023  润新知