• SPOJ705 SUBST1


    给一个字符串求有多少个不相同子串。

    每一个子串一定都是某一个后缀的前缀。由此可以推断出总共有(1+n)*n/2个子串,那么下面的任务就是找这些子串中重复的子串。

    在后缀数组中后缀都是排完序的,从sa[1]到sa[n],这么思考以某个串为前缀的子串有几个,那么容易想到重复子串的个数其实就是∑height[i]。

    所以结果就是(1+n)*n/2-∑height[i]。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define INF (1<<30)
     6 #define MAXN 55000
     7 
     8 int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
     9 int cmp(int *r,int a,int b,int l){
    10     return r[a]==r[b] && r[a+l]==r[b+l];
    11 }
    12 int sa[MAXN],rank[MAXN],height[MAXN];
    13 void SA(int *r,int n,int m){
    14     int *x=wa,*y=wb;
    15 
    16     for(int i=0; i<m; ++i) ws[i]=0;
    17     for(int i=0; i<n; ++i) ++ws[x[i]=r[i]];
    18     for(int i=1; i<m; ++i) ws[i]+=ws[i-1];
    19     for(int i=n-1; i>=0; --i) sa[--ws[x[i]]]=i;
    20 
    21     int p=1;
    22     for(int j=1; p<n; j<<=1,m=p){
    23         p=0;
    24         for(int i=n-j; i<n; ++i) y[p++]=i;
    25         for(int i=0; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
    26         for(int i=0; i<n; ++i) wv[i]=x[y[i]];
    27         for(int i=0; i<m; ++i) ws[i]=0;
    28         for(int i=0; i<n; ++i) ++ws[wv[i]];
    29         for(int i=1; i<m; ++i) ws[i]+=ws[i-1];
    30         for(int i=n-1; i>=0; --i) sa[--ws[wv[i]]]=y[i];
    31         swap(x,y); x[sa[0]]=0; p=1;
    32         for(int i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    33     }
    34 
    35     for(int i=1; i<n; ++i) rank[sa[i]]=i;
    36     int k=0;
    37     for(int i=0; i<n-1; height[rank[i++]]=k){
    38         if(k) --k;
    39         for(int j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k);
    40     }
    41 }
    42 
    43 char str[MAXN];
    44 int r[MAXN],n;
    45 int main(){
    46     int t;
    47     scanf("%d",&t);
    48     while(t--){
    49         scanf("%s",str);
    50         n=0;
    51         for(int i=0; str[i]; ++i){
    52             r[n++]=str[i];
    53         }
    54         r[n]=0;
    55         SA(r,n+1,128);
    56         long long cnt=0;
    57         for(int i=2; i<=n; ++i){
    58             cnt+=height[i];
    59         }
    60         printf("%lld
    ",(long long)(1+n)*n/2-cnt);
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    去中心化共识
    创建你的第一个去中心化应用(dapp)
    务实的去中心化
    什么是去中心化市场(OpenBazaar)
    为什么要做去中心化市场(OpenBazaar)
    区块链让物联网真正实现去中心化
    去中心化市场OpenBazaar如何运转
    如何安装去中心化市场(OpenBazaar)
    android自定义View&自定义ViewGroup(上)
    android自定义View&自定义ViewGroup(上)
  • 原文地址:https://www.cnblogs.com/WABoss/p/5203471.html
Copyright © 2020-2023  润新知