码迷,mamicode.com
首页 > 编程语言 > 详细

[Codechef CHSTR] Chef and String - 后缀数组

时间:2019-11-01 22:30:38      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:inline   cout   ring   bit   har   esc   一个   math   pac   

[Codechef CHSTR] Chef and String

Description

每次询问 \(S\) 的子串中,选出 \(k\) 个相同子串的方案有多少种。

Solution

本题要求不是很高,\(O(n^2)\) 统计每个出现次数子串个数即可。

我因为一个lld WA了一晚上(猛然意识到要%d读入long long的时候,之前一直没有翻车的原因是开了全局,如果是局部又不初始化就瞬间gg了,然鹅这个错误本地查不出来)

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,q,m=256,sa[200005],y[200005],u[200005],v[200005],o[200005],r[200005],h[200005],T;
int buf[200005],answer[200005];
char str[200005];
int C[5005][5005];
const int modulo = 1e+9+7;

signed main()
{
    C[0][0]=1;
    for(int i=1;i<=5000;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++)
        {
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%modulo;
        }
    }
    scanf("%lld",&T);
    while(T--)
    {
        memset(sa,0,sizeof sa);
        memset(y,0,sizeof y);
        memset(u,0,sizeof u);
        memset(v,0,sizeof v);
        memset(o,0,sizeof o);
        memset(r,0,sizeof r);
        memset(h,0,sizeof h);
        memset(buf,0,sizeof buf);
        memset(answer,0,sizeof answer);
        memset(str,0,sizeof str);
        scanf("%lld%lld",&n,&q);
        scanf("%s",str+1);

        for(int i=1; i<=n; i++) u[str[i]]++;
        for(int i=1; i<=m; i++) u[i]+=u[i-1];
        for(int i=n; i>=1; i--) sa[u[str[i]]--]=i;
        r[sa[1]]=1;
        for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);

        for(int l=1; r[sa[n]]<n; l<<=1)
        {
            memset(u,0,sizeof u);
            memset(v,0,sizeof v);
            memcpy(o,r,sizeof r);
            for(int i=1; i<=n; i++) u[r[i]]++, v[r[i+l]]++;
            for(int i=1; i<=n; i++) u[i]+=u[i-1], v[i]+=v[i-1];
            for(int i=n; i>=1; i--) y[v[r[i+l]]--]=i;
            for(int i=n; i>=1; i--) sa[u[r[y[i]]]--]=y[i];
            r[sa[1]]=1;
            for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
        }
        {
            int i,j,k=0;
            for(int i=1; i<=n; h[r[i++]]=k)
                for(k?k--:0,j=sa[r[i]-1]; str[i+k]==str[j+k]; k++);
        }
        buf[1]=n*(n+1ll)/2ll;
        for(int i=1; i<=n; i++) buf[1]-=h[i];
        for(int i=1; i<=n; i++)
        {
            int l=h[i],r=h[i+1];
            if(l<r)
            {
                ++l;
                for(int j=i+1; j<=n+1 && l<=r; j++)
                {
                    while(r>h[j]&&l<=r)
                    {
                        buf[j-i]++;
                        --r;
                    }
                }
            }
        }
        for(int i=2;i<=n;i++) buf[1] -= buf[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                (answer[i]+=(C[j][i]*buf[j])%modulo) %= modulo;
            }
        }
        //for(int i=1;i<=n;i++) cout<<buf[i]<<" ";
        //cout<<endl;1
        for(int i=1;i<=q;i++)
        {
            int tmp;
            scanf("%lld",&tmp);
            if(tmp<=n) printf("%lld\n",answer[tmp]);
            else printf("0\n");
        }
    }
}

[Codechef CHSTR] Chef and String - 后缀数组

标签:inline   cout   ring   bit   har   esc   一个   math   pac   

原文地址:https://www.cnblogs.com/mollnn/p/11779668.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!