zoukankan      html  css  js  c++  java
  • SPOJ 694/705 后缀数组

    题意:

    求单个子串的不重复子串个数

    题解:

    一个字符串中的所有子串都必然是它的后缀的前缀。

    对于每一个sa[i]后缀,它的起始位置sa[i],那么它最多能得到该后缀长度个子串(n-sa[i]个),而其中有height[i]个是与前一个后缀相同的,所以它能产生的实际后缀个数便是n-sa[i]-height[i]。遍历一次所有的后缀,将它产生的后缀数加起来便是答案。

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <algorithm>
     6 
     7 #define N 50050
     8 
     9 using namespace std;
    10 
    11 int wa[N],wb[N],wc[N],wv[N];
    12 int r[N],sa[N];
    13 char str[N];
    14 int rank[N],height[N];
    15 
    16 inline bool cmp(int *r,int a,int b,int l)
    17 {
    18     return r[a]==r[b]&&r[a+l]==r[b+l];
    19 }
    20 
    21 inline void da(int *r,int *sa,int n,int m)
    22 {
    23     int i,j,p,*x=wa,*y=wb,*t;
    24     for(i=0;i<m;i++) wc[i]=0;
    25     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
    26     for(i=1;i<m;i++) wc[i]+=wc[i-1];
    27     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
    28     for(j=1,p=1;p<n;j<<=1,m=p)
    29     {
    30         for(i=n-j,p=0;i<n;i++) y[p++]=i;
    31         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    32         for(i=0;i<n;i++) wv[i]=x[y[i]];
    33         for(i=0;i<m;i++) wc[i]=0;
    34         for(i=0;i<n;i++) wc[wv[i]]++;
    35         for(i=1;i<m;i++) wc[i]+=wc[i-1];
    36         for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i];
    37         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
    38             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    39     }
    40 }
    41 
    42 inline void getheight(int *r,int *sa,int n)
    43 {
    44     int i,j,k=0;
    45     for(i=1;i<=n;i++) rank[sa[i]]=i;
    46     for(i=0;i<n;height[rank[i++]]=k)
    47         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
    48 }
    49 
    50 inline void go()
    51 {
    52     int n,ans=0;
    53     scanf("%s",str);
    54     n=strlen(str);
    55     for(int i=0;i<n;i++) r[i]=str[i];
    56     r[n]=0;
    57     da(r,sa,n+1,256);
    58     getheight(r,sa,n);
    59     for(int i=1;i<=n;i++) ans+=n-sa[i]-height[i];
    60     printf("%d\n",ans);
    61 }
    62 
    63 int main()
    64 {
    65     int cas;scanf("%d",&cas);
    66     while(cas--) go();
    67     return 0;
    68 }
  • 相关阅读:
    SpringMVC-Day1 (课题有用)
    Spring-Day3
    Spring-Day2
    fix mac
    新西兰产假(陪产假)
    nz 国内航空
    英文句子
    centos7.2安装swoole扩展
    linux搭建vue框架部署环境
    微信扫描带参数二维码事件
  • 原文地址:https://www.cnblogs.com/proverbs/p/2893405.html
Copyright © 2011-2022 走看看