HDU 3336【前缀出现次数】dp+kmp

4 篇文章 0 订阅

HDU 3336【前缀出现次数】dp+kmp

  • 题意:求出字符串前缀出现的总次数,答案对1e4+7取模;
  • 思路:我们先考虑kmp匹配前缀与自身,可惜是O(n*n)的复杂度,那么我们该怎样匹配呢?对于这样一个串,在这里插入图片描述
  • 我们可以很容易发现这样一件事cnt[s1]=cnt[s2]=cnt[s3]+1;我们初始化cnt[i]=1;然后从后往前累加cnt[nxt[i]]+=cnt[i],每出现一次长串,就会贡献自身的次数,为什么要倒着扫呢?因为长串对短串才有贡献。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e4+7;
char x[200100];
int nt[200100],m,cnt[200100];///cnt[i]代表长度为i的前缀出现次数
void kmp()
{
    int i,j;
    j=nt[0]=-1;
    i=0;
    while(i<m)
    {
        while(j!=-1 &&  x[i]!=x[j])
            j=nt[j];
        nt[++i]=++j;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>m;
        scanf("%s",x);
        m=strlen(x);
        kmp();
        ll ans=0;
        fill(cnt,cnt+m+1,1);
        for(int i=m; i>=1; i--)
            cnt[nt[i]]+=cnt[i];
        for(int i=1; i<=m; i++)
            (ans+=cnt[i])%=mod;
        printf("%lld\n",ans);
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值