zoukankan      html  css  js  c++  java
  • spoj 694. Distinct Substrings 后缀数组求不同子串的个数

    题目链接:http://www.spoj.com/problems/DISUBSTR/

    思路:

    每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数。如果所有的后缀按照suffix(sa[1]),suffix(sa[2]),suffix(sa[3]),……suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来的后缀suffix(sa[k]),它将产生n-sa[k]+1个新的前缀。但是其中有height[k]个是和前面的字符串的前缀是相同的。所以suffix(sa[k])将“贡献”出n-sa[k]+1-height[k]个不同的子串。累加后便是原问题的答案。这个做法的时间复杂度为O(na)。

    代码如下:

     1 #include<cstring>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<iostream>
     6 using namespace std;
     7 const int maxn=1010;
     8 int wa[maxn],wb[maxn],wv[maxn],wq[maxn];
     9 int rank[maxn],sa[maxn];
    10 int r[maxn];
    11 char s[maxn];
    12 int height[maxn];
    13 int cmp(int *r,int a,int b,int l)
    14 {return r[a]==r[b]&&r[a+l]==r[b+l];}
    15 void da(int* r,int *sa,int n,int m)
    16 {
    17     int i,j,p,*x=wa,*y=wb,*t;
    18     for(i=0;i<m;i++) wq[i]=0;
    19     for(i=0;i<n;i++) wq[x[i]=r[i]]++;
    20     for(i=1;i<m;i++) wq[i]+=wq[i-1];
    21     for(i=n-1;i>=0;i--) sa[--wq[x[i]]]=i;
    22 
    23     for(j=1,p=1;p<n;j*=2,m=p)
    24     {
    25         for(p=0,i=n-j;i<n;i++) y[p++]=i;
    26         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    27         for(i=0;i<n;i++) wv[i]=x[y[i]];
    28         for(i=0;i<m;i++) wq[i]=0;
    29         for(i=0;i<n;i++) wq[wv[i]]++;
    30         for(i=1;i<m;i++) wq[i]+=wq[i-1];
    31         for(i=n-1;i>=0;i--) sa[--wq[wv[i]]]=y[i];
    32         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
    33         x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    34 
    35     }
    36     return ;
    37  
    38 }
    39 void callheight(int *r,int n)
    40 {
    41     int i,j,k=0;
    42     for(i=1;i<=n;i++) rank[sa[i]]=i;
    43     for(i=0;i<n;i++)
    44        {
    45            if(k) k--;
    46            j=sa[rank[i]-1];
    47            while(r[i+k]==r[j+k]) k++;
    48            height[rank[i]]=k;
    49        }
    50 }
    51 int main()
    52  {
    53       int t;
    54       scanf("%d",&t);
    55       while(t--)
    56       {
    57         scanf("%s",s);
    58 
    59         int n=strlen(s);
    60         for(int i=0;i<n;i++)
    61             r[i]=s[i];
    62             r[n]=0;
    63             da(r,sa,n+1,130);
    64             callheight(r,n);
    65            int ans=0;
    66         for(int i=1;i<=n;i++)
    67             ans+=(n-sa[i]-height[i]);
    68         cout<<ans<<endl;
    69        
    70       }
    71       return 0;
    72  }
    View Code
  • 相关阅读:
    Liunx之django项目部署
    Liunx之nginx配置
    Liunx之基础学习
    Linux之防火墙【CentOS 7】
    Linux之各程序安装
    Linux之基础命令
    攻城狮必备神注释
    Django-rbac权限
    "/var/lib/mysql/mysql.sock"不存在解决办法
    72张三国历史演变地图
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/spoj694.html
Copyright © 2011-2022 走看看