zoukankan      html  css  js  c++  java
  • [AHOI2013]差异

    题目描述

    给定一个长度为 $n$ 的字符串 $S$ ,令 $T_i$ 表示它从第 $i$ 个字符开始的后缀。求

    $displaystyle sum_{1leqslant i<jleqslant n} ext{len}(T_i)+ ext{len}(T_j)-2 imes ext{lcp}(T_i,T_j)$

    其中,$ ext{len}(a)$ 表示字符串 $a$ 的长度,$ ext{lcp}(a,b)$ 表示字符串 $a$ 和字符串 $b$ 的最长公共前缀。

    输入输出格式

    输入格式:

    一行,一个字符串 $S$ 。

    输出格式:

    一行,一个整数,表示所求值。

    输入输出样例

    输入样例#1: 复制
    cacao
    输出样例#1: 复制
    54

    说明

    对于 100% 的数据,保证 $2leqslant nleqslant 500000$ ,且均为小写字母。

    先用后缀数组求出height数组(h数组)

    那么两个点i,j的LCP就是$min{h[k] | i+1<=k<=j}$

    考虑每个h[i]的贡献

    假设L[i]表示L[i]~i-1的h值都大于等于h[i]

    而R[i]表示i+1~R[i]的h值大于h[i](之所以不是大于等于是为了避免相同的h带来重复答案)

    $ans-=2*lcp(T_i,T_j)$

    $ans-=2*(i-L[i]+1)*(R[i]-i+1)*h[i]$

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long lol;
     8 int n,m,c[600001];
     9 int x[600001],y[600001],SA[600001],s[600001],rank[600001],st[600001],top;
    10 lol L[600001],R[600001];
    11 lol h[600001],ans,sum;
    12 char ch[600001];
    13 void radix_sort()
    14 {int i;
    15   for (i=0;i<m;i++)
    16     c[i]=0;
    17   for (i=0;i<n;i++)
    18     c[x[y[i]]]++;
    19   for (i=1;i<m;i++)
    20     c[i]+=c[i-1];
    21   for (i=n-1;i>=0;i--)
    22     SA[--c[x[y[i]]]]=y[i];
    23 }
    24 void build()
    25 {int i,j,k,p;
    26   for (i=0;i<n;i++)
    27     y[i]=i,x[i]=s[i];
    28   m=500000;
    29   radix_sort();
    30   for (k=1;k<=n;k*=2)
    31     {
    32       p=0;
    33       for (i=n-k;i<n;i++)
    34     y[p++]=i;
    35       for (i=0;i<n;i++)
    36     if (SA[i]>=k) y[p++]=SA[i]-k;
    37       radix_sort();
    38       p=1;swap(x,y);
    39       x[SA[0]]=0;
    40       for (i=1;i<n;i++)
    41     x[SA[i]]=((y[SA[i]]==y[SA[i-1]])&&((SA[i]+k<n?y[SA[i]+k]:-1)==(SA[i-1]+k<n?y[SA[i-1]+k]:-1)))?p-1:p++;
    42       if (p>n) break;
    43       m=p;
    44     }
    45   for (i=0;i<n;i++)
    46     rank[SA[i]]=i;
    47   int len=0;
    48   for (i=0;i<n;i++)
    49     if(rank[i]>0)
    50     {
    51       if (len) len--;
    52       j=SA[rank[i]-1];
    53       while (i+len<n&&j+len<n&&(s[i+len]==s[j+len])) len++;
    54       h[rank[i]]=len;
    55     }
    56 }
    57 int main()
    58 {int i,j;
    59   cin>>ch;
    60   n=strlen(ch);
    61   for (i=0;i<n;i++)
    62     {
    63       s[i]=ch[i]-'a'+1;
    64     }
    65   build();
    66   for (i=0;i<n;i++)
    67     {
    68       while (top&&h[i]<=h[st[top]]) top--;
    69       if (top==0) L[i]=0;
    70       else L[i]=st[top]+1;
    71       st[++top]=i;
    72     }
    73   top=0;
    74   for (i=n-1;i>=0;i--)
    75     {
    76       while (top&&h[i]<h[st[top]]) top--;
    77       if (top==0) R[i]=n-1;
    78       else R[i]=st[top]-1;
    79       st[++top]=i;
    80     }
    81   for (i=1;i<=n;i++)
    82     ans+=(lol)i*(lol)(n-1);
    83   for (i=0;i<n;i++)
    84     {
    85       ans-=2ll*((lol)i-(lol)L[i]+1ll)*((lol)R[i]-(lol)i+1ll)*(lol)h[i];
    86     }
    87   printf("%lld
    ",ans);
    88 }
  • 相关阅读:
    存储过程sql拼接
    收集 一个数字转大写金额的方法
    判断打印机是否可用
    TortoiseSVN解决冲突
    特殊符号
    [转]Winform用匿名方法新建线程的方法
    [转]利用SqlBulkCopy快速大批量导入数据(SqlBulkCopy强大)
    DevExpress GridControl使用
    GridView自动调整列宽
    'display','position'和'float'相互关系
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8474366.html
Copyright © 2011-2022 走看看