Count the string (kmp的next数组运用)

【题目来源】https://cn.vjudge.net/problem/HDU-3336
【题意】
给出一个字符串,假设这个字符串长度为n,那么这个字符串的所有前缀字符串在原字符出现次数是多少。
举个例子:
s: “abab”
The prefixes are: “a”, “ab”, “aba”, “abab”
res=2+2+1+1=6。
【思路】
起初并没有想到用next数组去解决问题,而是想着是否可以暴力。。
大神们说可以动规,但是实力有限的我找不到对应的关系。所以只好作罢。
然后大神提醒我用next数组去解决问题。
忽然发现next数组表示的含义刚好可以用来解决这道题。
只要next数值不为0,不为-1,那么代表一定能够和前面匹配,既然能匹配,说明当前位置的字符串之前出现过,所以只要统计数值不为0和-1的次数,再加上最基础的n个字符串,什么是基础的呢?举个例子,假如字符串为ababa,那么基础的就是:
a
ab
aba
abab
ababa。
【代码】

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<limits.h>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int mod=1e9+7;
const double esp=1e-5;
typedef unsigned long long ll;
typedef long long LL;
char s[200000+10];
int nexx[200000+10];
int n;
void get_next()
{
    int i=0,j;
    j=nexx[0]=-1;
    while(i<n)
    {
        while(-1!=j&&s[i]!=s[j]) j=nexx[j];
        nexx[++i]=++j;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        scanf("%s",s);
        get_next();
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            if(nexx[i]>0)
            {
                ans++;
                if(ans>=10007)
                    ans-=10007;
            }
        }
        ans+=n;
        printf("%d\n",ans%10007);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值