hdu 3336

<span style="background-color: rgb(0, 153, 0);">/*题意:就是让给你一个字符串,然后计算不断增加的前缀字符串在整个字符创当中出现的次数和,可能出现的次数过大,所以要求结果1007.
例如:abab a 2 ab 2 aba 1 abab 1  2+2+1+1=6
*/
/*思路:其实我们想想比如对于位置i来说,现在我们求出了f[i]的值,那么[0,f[i]-1]串就是一个
能匹配i-1位置的最长的前缀串。且我们根据f[i]的值可以定位其他所有可匹配的前缀。KMP的思想
就是找出每个位置i的可匹配最大前缀j。令dp[i]表示S[0,i-1]串的后缀能匹配的前缀个数,
那么dp[i]=dp[next[i]]+1, dp[1]=1正好表示串s[0]的后缀只能匹配串s[0].
*/</span>


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pp;
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxl 200020
#define mem(i,j) memset(i,j,sizeof(i))
const int mod=10007;
int f[maxl],d[maxl],len;
char s[maxl];
void getnext(char *s,int *f){
    f[0]=f[1]=0;
    for(int i=1;i<len;i++){
        int j=f[i];
        while(j&&s[i]!=s[j]) j=f[j];//这里不断的替换来降低复杂度
        f[i+1]=(s[i]==s[j])?j+1:0;//f[i+1]保存的是s[i]的前缀的长度
    }
}

int main()
{
  //freopen("in.txt", "r", stdin);
    int t;
    cin>>t;
    while(t--){
        cin>>len>>s;
        getnext(s,f);
        memset(d,0,sizeof(d));
        int ans=0;
        for(int i=1;i<=len;i++){
            d[i]=d[f[i]]+1;//因为f[i]记录的是i-1的前缀的长度 但是不知道它的次数 后面的是在前面的结果上面累加的 所以每次加1 直到后面如果还是有相同的前缀的时候已经累加上去了
            ans=(ans+d[i])%mod;
        }
        cout<<ans<<endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值