zoukankan      html  css  js  c++  java
  • SPOJ Distinct Substrings

    给定一个字符串,求不相同子串个数。
    每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同子串个数。
    总数为n*(n-1)/2,再减掉height[i]的和就是答案

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e6+14;
    int sa[maxn];
    int t1[maxn];
    int t2[maxn];
    int c[maxn];
    int rk[maxn];
    int height[maxn];
    void build_sa (int s[],int n,int m) {
        int i,j,p;
        int *x=t1,*y=t2;
        for (i=0;i<m;i++) c[i]=0;
        for (i=0;i<n;i++) c[x[i]=s[i]]++;
        for (i=1;i<m;i++) c[i]+=c[i-1];
        for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
        for (j=1;j<=n;j<<=1) {
            p=0;
            for (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<m;i++) c[i]=0;
            for (i=0;i<n;i++) c[x[y[i]]]++;
            for (i=1;i<m;i++) c[i]+=c[i-1];
            for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;
            x[sa[0]]=0;
            for (i=1;i<n;i++) 
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
            if (p>=n) break;
            m=p; 
        }
    }
    void getHeight (int s[],int n) {
        int i,j,k=0;
        for (i=0;i<=n;i++) rk[sa[i]]=i;
        for (i=0;i<n;i++) {
            if (k) k--;
            j=sa[rk[i]-1];
            while (s[i+k]==s[j+k]) k++;
            height[rk[i]]=k;
        }
    }
    bool check (int n,int k,int t) {
        int num=1;
        for (int i=2;i<=n;i++) {
            if (height[i]>=t) {
                num++;
                if (num>=k) return true;
            }
            else num=1;
        }
        return false;
    }
    char str[maxn];
    int s[maxn];
    int main () {
        int T;
        scanf ("%d",&T);
        while (T--) {
            scanf ("%s",str);
            int n=strlen(str);
            for (int i=0;i<=n;i++) s[i]=str[i];
            build_sa(s,n+1,128);
            getHeight(s,n);
            int ans=n*(n+1)/2;
            for (int i=2;i<=n;i++) ans-=height[i];
            printf ("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12332660.html
Copyright © 2011-2022 走看看