zoukankan      html  css  js  c++  java
  • 有多少个不同的子串?-- 后缀数组

     题目大意: 给你一个字符串问你有多少个不相同的子串?

    Input

    T- number of test cases. T<=20; Each test case consists of one string, whose length is <= 50000

    output

    For each test case output one number saying the number of distinct substrings.

    Example

    Input:
    2
    CCCCC
    ABABA
    
    Output:
    5
    9


    题目思路:利用后缀数组这个工具,不会后缀数组详见  后缀数组论文链接——处理字符串的有力工具_百度文库。这篇文章说的比较详细,思路就是一共会有 n*(n+1)/2  减去重复的就可以了,
    举个栗子.   ABABA  比如这个.他的后缀排序之后是:
    • A  -------------------后缀 a
    • ABA  ---------------后缀 b
    • ABABA    ----------后缀 c
    • BA  -----------------后缀 d
    • BABA  -------------后缀 e
    这样,重复的子串就是 (a,b)的最长公共前缀长度
    答案就是 15 - {  lcp(a,b)=1  } - {  lcp(b,c)=3  } - {  lcp(c,d)=0  } - {  lcp(d,e)=2  }
                 =15-1-3-0-2=9;

    下面是模板代码

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<string>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    #include<stdlib.h>
    #include<time.h>
    
    using namespace std;
    typedef long long LL;
    const int INF=2e9+1e8;
    const int MOD=1e9+7;
    const int MAXSIZE=1e6+5;
    const double eps=0.0000000001;
    void fre()
    {
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    }
    #define memst(a,b) memset(a,b,sizeof(a))
    #define fr(i,a,n) for(int i=a;i<n;i++)
    
    int rankarr[MAXSIZE],wa[MAXSIZE],wb[MAXSIZE],height[MAXSIZE];
    int wvarr[MAXSIZE],wsarr[MAXSIZE],SA[MAXSIZE];
    char str[MAXSIZE];
    
    int cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void da(char *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0; i<m; i++) wsarr[i]=0;
        for(i=0; i<n; i++) wsarr[x[i]=r[i]]++;
        for(i=1; i<m; i++) wsarr[i]+=wsarr[i-1];
        for(i=n-1; i>=0; i--) sa[--wsarr[x[i]]]=i;
        for(j=1,p=1; p<n; j<<=1,m=p)
        {
            for(p=0,i=n-j; i<n; i++) y[p++]=i;
            for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0; i<n; i++) wvarr[i]=x[y[i]];
            for(i=0; i<m; i++) wsarr[i]=0;
            for(i=0; i<n; i++) wsarr[wvarr[i]]++;
            for(i=1; i<m; i++) wsarr[i]+=wsarr[i-1];
            for(i=n-1; i>=0; i--) sa[--wsarr[wvarr[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
        return;
    }
    void calheight(char *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1; i<=n; i++) rankarr[sa[i]]=i;
        for(i=0; i<n; height[rankarr[i++]]=k)
            for(k?k--:0,j=sa[rankarr[i]-1]; r[i+k]==r[j+k]; k++);
        return;
    }
    LL solve(int n)
    {
        LL ans=n;
        for(int i=2;i<=n;i++)
            ans+=n-i+1-height[i];
        return ans;
    }
    int main()
    {
        int ncase;
        cin>>ncase;
        while(ncase--)
        {
            scanf("%s",str);
            int n=strlen(str);
            str[n]=0;
            da(str,SA,n+1,128);
            calheight(str,SA,n);
            cout<<solve(n)<<endl;
        }
        return 0;
    }
    



  • 相关阅读:
    POJ 2752 Seek the Name, Seek the Fame
    POJ 2406 Power Strings
    KMP 算法总结
    SGU 275 To xor or not to xor
    hihocoder 1196 高斯消元.二
    hihoCoder 1195 高斯消元.一
    UvaLive 5026 Building Roads
    HDU 2196 computer
    Notions of Flow Networks and Flows
    C/C++代码中的笔误
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7207947.html
Copyright © 2011-2022 走看看