zoukankan      html  css  js  c++  java
  • spoj705 后缀数组求不同子串的个数

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

    SUBST1 - New Distinct Substrings

    no tags 

    Given a string, we need to find the total number of its distinct substrings.

    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
    题意:
    求不同的子串的个数。
    思路:
    每一个子串都是某一个后缀的前缀。所以对于当前的后缀,他能够贡献的个数就是他的长度减去
    rank[i]-1的那个的公共前缀长度。
     
    /*
     * Author:  sweat123
     * Created Time:  2016/6/29 13:46:26
     * File Name: main.cpp
     */
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<time.h>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 1<<30
    #define MOD 1000000007
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define pi acos(-1.0)
    using namespace std;
    const int MAXN = 50010;
    char s[MAXN];
    int wa[MAXN],wb[MAXN],wc[MAXN],n,height[MAXN],r[MAXN],Rank[MAXN],sa[MAXN];
    void da(int *r,int *sa,int n,int m){
        int *x = wa,*y = wb;
        for(int i = 0; i < m; i++)wc[i] = 0;
        for(int i = 0; i < n; i++)wc[x[i] = r[i]] ++;
        for(int i = 0; i < m; i++)wc[i] += wc[i-1];
        for(int i = n - 1; i >= 0; i--)sa[--wc[x[i]]] = i;
        for(int p = 1,k = 1; p < n; m = p,k <<= 1){
            p = 0;
            for(int i = n - k; i < n; i++)y[p++] = i;
            for(int i = 0; i < n; i++)if(sa[i] >= k)y[p++] = sa[i] - k;
            for(int i = 0; i < m; i++)wc[i] = 0;
            for(int i = 0; i < n; i++)wc[x[y[i]]] ++;
            for(int i = 0; i < m; i++)wc[i] += wc[i-1];
            for(int i = n - 1; i >= 0; i--)sa[--wc[x[y[i]]]] = y[i];
            swap(x,y);
            p = 1;
            x[sa[0]] = 0;
            for(int i = 1; i < n; i++){
                x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k])?p-1:p++;   
            }
        }   
    }
    void calheight(int *r,int *sa,int n){
        for(int i = 1; i <= n; i++)Rank[sa[i]] = i;
        int j,k;
        k = 0;
        for(int i = 0; i < n; height[Rank[i++]] = k){
            for(k?k--:0,j = sa[Rank[i]-1]; r[j+k] == r[i+k]; k++);
        }   
    }
    void solve(){
        int ans = 0;
        for(int i = 1; i <= n; i++){
            int tp = height[i];
            int len = n - sa[i];
            ans += len - tp;
        }   
        printf("%d
    ",ans);
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%s",s);
            n = strlen(s);
            for(int i = 0; i < n; i++){
                r[i] = s[i];
            }   
            r[n] = 0;
            da(r,sa,n+1,128);
            calheight(r,sa,n);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    洛谷P4548 [CTSC2006]歌唱王国(概率生成函数)
    洛谷P3643 [APIO2016]划艇(组合数学)
    洛谷T46780 ZJL 的妹子序列(生成函数)
    洛谷P4220 [WC2018]通道(边分治+虚树)
    洛谷P4931 情侣?给我烧了!(加强版)(组合数学)
    洛谷P4451 [国家集训队]整数的lqp拆分(生成函数)
    thinkphp5.0 页面缓存
    thinkphp5.0 cache数据缓存机制
    laravel 视图调用方法并传递参数
    laravel 安装配置前准备
  • 原文地址:https://www.cnblogs.com/sweat123/p/5627008.html
Copyright © 2011-2022 走看看