zoukankan      html  css  js  c++  java
  • [BZOJ3238][AHOI2013]差异(后缀数组)

    求和式的前两项可以直接算,问题是对于每对i,j计算LCP。

    一个比较显然的性质是,LCP(i,j)是h[rk[i]+1~rk[j]]中的最小值。

    从h的每个元素角度考虑,就是对每个h计算有多少对i,j以它为最小值。

    在h中使用单调栈统计左右比它小的第一个元素,相乘得到结果。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 typedef long long ll;
     6 using namespace std;
     7 
     8 const int N=1000010,inf=1000000000;
     9 ll ans;
    10 char s[N];
    11 int n,top,x[N],y[N],c[N],sa[N],h[N],rk[N],l[N],r[N],stk[N];
    12 int Cmp(int a,int b,int l){ return a+l<=n && b+l<=n && y[a]==y[b] && y[a+l]==y[b+l]; }
    13 
    14 void build_sa(int m){
    15     memset(y,0,sizeof(y));
    16     rep(i,0,m) c[i]=0;
    17     rep(i,1,n) c[x[i]=s[i]-'a'+1]++;
    18     rep(i,1,m) c[i]+=c[i-1];
    19     for (int i=n; i; i--) sa[c[x[i]]--]=i;
    20     for (int k=1,p=0; p<n; k<<=1,m=p){
    21          p=0;
    22          rep(i,n-k+1,n) y[++p]=i;
    23          rep(i,1,n) if (sa[i]>k) y[++p]=sa[i]-k;
    24          rep(i,0,m) c[i]=0;
    25          rep(i,1,n) c[x[y[i]]]++;
    26          rep(i,1,m) c[i]+=c[i-1];
    27          for (int i=n; i; i--) sa[c[x[y[i]]]--]=y[i];
    28          rep(i,1,n) y[i]=x[i]; p=1; x[sa[1]]=1;
    29          rep(i,2,n) x[sa[i]]=Cmp(sa[i-1],sa[i],k) ? p : ++p;
    30     }
    31 }
    32 
    33 void get(){
    34     int k=0;
    35     rep(i,1,n) rk[sa[i]]=i;
    36     rep(i,1,n){
    37          for (int j=sa[rk[i]-1]; i+k<=n && j+k<=n && s[i+k]==s[j+k]; k++);
    38          h[rk[i]]=k; if (k) k--;
    39     }
    40 }
    41 
    42 void solve(){
    43     rep(i,1,n) ans+=1ll*i*(n-1);
    44     h[0]=-inf;
    45     rep(i,1,n){
    46         while (h[i]<=h[stk[top]]) top--;
    47         if (!stk[top]) l[i]=1; else l[i]=stk[top]+1;
    48         stk[++top]=i;
    49     }
    50     h[n+1]=-inf; top=0; stk[0]=n+1;
    51     for (int i=n; i; i--){
    52         while (h[i]<h[stk[top]]) top--;
    53         if (stk[top]==n+1) r[i]=n; else r[i]=stk[top]-1;
    54         stk[++top]=i;
    55     }
    56     rep(i,1,n) ans-=2ll*(i-l[i]+1)*(r[i]-i+1)*h[i];
    57 }
    58 
    59 int main(){
    60     freopen("bzoj3238.in","r",stdin);
    61     freopen("bzoj3238.out","w",stdout);
    62     scanf("%s",s+1); n=strlen(s+1);
    63     build_sa(300); get(); solve(); printf("%lld
    ",ans);
    64     return 0;
    65 }
  • 相关阅读:
    格式化字符串漏洞利用实战之 0ctf-easyprintf
    java多线程机制中的Thread和Runnable()区别
    Eclipse中部署Android开发环境插件安装问题方案
    java接口实现
    Visual Studio UML
    java子类继承关系
    Visual Studio UML类图
    java方法重载和重写
    javaSocket笔记
    python网络爬虫笔记(九)
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9441294.html
Copyright © 2011-2022 走看看