zoukankan      html  css  js  c++  java
  • SPOJ705-New Distinct Substrings-后缀数组

    计算所都不相同子串的个数,做法是所有子串的个数减去sigma(height[]).其中height数组的和便是所有相同子串的个数。

    注意 N×(N+1)/2会爆int!但是最终答案在int内。所以使用sigma(n-sa[i]+1-height[i])的做法不会wa

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int maxn = 5e4+10;
     8 char line[maxn];
     9 int s[maxn];
    10 int sa[maxn],t1[maxn],t2[maxn],c[maxn];
    11 int rank[maxn],height[maxn];
    12 
    13 void build_sa(int s[],int n,int m)
    14 {
    15     int i,j,p,*x=t1,*y=t2;
    16     //第一轮基数排序,如果s的最大值很大,可改为快速排序
    17     for(i=0;i<m;i++)c[i]=0;
    18     for(i=0;i<n;i++)c[x[i]=s[i]]++;
    19     for(i=1;i<m;i++)c[i]+=c[i-1];
    20     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    21     for(j=1;j<=n;j<<=1)
    22     {
    23         p=0;
    24         //直接利用sa数组排序第二关键字
    25         for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
    26         for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
    27         //这样数组y保存的就是按照第二关键字排序的结果
    28         //基数排序第一关键字
    29         for(i=0;i<m;i++)c[i]=0;
    30         for(i=0;i<n;i++)c[x[y[i]]]++;
    31         for(i=1;i<m;i++)c[i]+=c[i-1];
    32         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
    33         //根据sa和x数组计算新的x数组
    34         swap(x,y);
    35         p=1;x[sa[0]]=0;
    36         for(i=1;i<n;i++)
    37             x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
    38         if(p>=n)break;
    39         m=p;//下次基数排序的最大值
    40     }
    41 }
    42 void getHeight(int s[],int n)
    43 {
    44     int i,j,k=0;
    45     for(i=0;i<=n;i++)rank[sa[i]]=i;
    46     for(i=0;i<n;i++)
    47     {
    48         if(k)k--;
    49         j=sa[rank[i]-1];
    50         while(s[i+k]==s[j+k])k++;
    51         height[rank[i]]=k;
    52     }
    53 }
    54 
    55 int T;
    56 
    57 int main()
    58 {
    59     scanf("%d",&T);
    60     while(T--)
    61     {
    62         scanf("%s",line);
    63         int N = strlen(line);
    64         for(int i=0;i<=N;i++)
    65             s[i] = line[i];
    66 
    67         build_sa(s,N+1,300);
    68         getHeight(s,N);
    69 
    70         long long len = N;
    71         long long ans = len*(len+1)/2;
    72 
    73         for(int i=2;i<=N;i++)
    74         {
    75             ans -= height[i];
    76         }
    77         printf("%d
    ",ans);
    78     }
    79 }
  • 相关阅读:
    MySql
    027 mysql
    navicat
    基于阿里云资源的分布式部署方案
    translate(50%,50%) 实现水平垂直居中
    SSH2 协议详解
    DNS服务配置篇 巴哥学Server2003
    Java 8 后的新功能梳理
    IBM Cognos BI 最佳实践系列 网站地址
    jsf2.0 入门视频 教程
  • 原文地址:https://www.cnblogs.com/helica/p/5510436.html
Copyright © 2011-2022 走看看