• 不同子串个数


    不同子串个数
    时间限制1.00 s
    内存限制125.00 MB

    题目背景

    因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题:

    题目描述

    给你一个长为N的字符串,求不同的子串的个数

    我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。

    子串的定义:原字符串中连续的一段字符组成的字符串

    输入格式

    第一行一个整数N

    接下来一行N个字符表示给出的字符串

    输出格式

    一行一个整数,表示不一样的子串个数

    输入输出样例

    输入 #1
    5
    aabaa
    输出 #1
    11
    输入 #2
    3
    aba
    输出 #2
    5

    说明/提示

    请使用64位整数来进行输出

    (具体来说,C++和C选手请使用long long 类型,pascal选手请使用Int64)

    由于输入文件过大,请使用 高效的读入方法(具体的,c++和c选手请不要使用cin,pascal选手不需要管)

    对于30%的数据,Nle 1000N1000

    对于100%的数据,Nle 10^5N105


    参考博客:https://www.luogu.org/blog/Elaborate/solution-p2408

    #include<bits/stdc++.h>
    const int N = 4e5+50;
    using namespace std;
    
    struct SuffixArray
    {
        int sa[N],rank[N],height[N],cnt[N],a1[N],a2[N],n,m,*x,*y;
        void sort()
        {
            for(int i=0; i<m; i++) cnt[i]=0;
            for(int i=0; i<n; i++) cnt[x[i]]++;
            for(int i=1; i<m; i++) cnt[i]+=cnt[i-1];
            for(int i=n-1; i>=0; i--) sa[--cnt[x[y[i]]]]=y[i];
        }
        void build(char *s,int c_size)
        {
            n=strlen(s);
            m=c_size;
            x=a1;
            y=a2;
            for(int i=0; i<n; i++) x[i]=s[i],y[i]=i;
            x[n]=y[n]=-1;
            sort();
            for(int k=1; k<=n; k<<=1)
            {
                int 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;
                sort();
                p=0;
                std::swap(x,y);
                x[sa[0]]=0;
                for(int i=1; i<n; i++)
                {
                    if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) p++;
                    x[sa[i]]=p;
                }
                if(p+1>=n) break;
                m=p+1;
            }
            for(int i=0; i<n; i++) rank[sa[i]]=i;
            height[0]=0;
            int k=0;
            for(int i=0; i<n; i++)
            {
                if(k) k--;
                if(rank[i]==0) continue;
                int j=sa[rank[i]-1];
                while(i+k<n&&j+k<n&&s[i+k]==s[j+k]) k++;
                height[rank[i]]=k;
            }
        }
    } SA;
    
    
    int main()
    {
        char s[N]= {0};
        long long len;
        scanf("%d %s",&len,s);
    
        SA.build(s,256);
    
        long long ans=len*(len+1)/2;
            
        for(int i=1; i<len; i++)
        {
            ans-=SA.height[i];
        }
    
        printf("%lld
    ",ans);//
        return 0;
    }
    View Code
  • 相关阅读:
    SpringBoot08-缓存
    Spring注解-自动装配(三)
    Spring注解-生命周期与属性赋值(二)
    Spring注解-组件注册(一)
    剖析SpringMVC流程与整合(八)
    SpringMVC视图解析与配置(六)
    SpringMVC的其他功能(七)
    简单了解SpringMVC(五)
    Java动态代理
    Spring事务(四)
  • 原文地址:https://www.cnblogs.com/tian-luo/p/11261974.html
Copyright © 2020-2023  润新知