hdu 3336 Count the string

http://acm.hdu.edu.cn/showproblem.php?pid=3336

根据TMP求next数组的原理我们发现:

给出任意数字i,它的next值为j(j>0),那么j-1代表str[0]~str[j-1]这个前缀再主串中出现一次。

由此轻松解决本题

AC代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

char str[200010];
int next[200010],n;

void getnext(){
    int i=0, j = -1;
    next[0] = -1;
    while(i < n){
        if(j == -1 || str[i] == str[j]){
            i++, j++;
            next[i] = j;
        }
        else j = next[j];
    }
}

int main(){
    int cas;
    scanf("%d",&cas);
    for(int i=0; i<cas; i++){
        scanf("%d",&n);
        scanf("%s",str);
        getnext();
        int ans = 0;
        for(int i=1; i<=n; i++)
            if(next[i]) ans++;
        ans %= 10007;
        ans += n%10007;
        ans %= 10007;
        printf("%d\n",ans);
    }
    //system("pause");
    return 0;
}

上述解法经指正是错误的,正确解法如下:

定义dp[i]表示已i结尾的前缀所包含的前缀数,那么dp[i] =dp[next[i]]+1。这个转移方程什么意思呢?结合abab讲解一下

 

next[i] = k,那么str[i-k+1~i]就和str[1~k]是完全匹配的,于是转移方程就显而易见。

AC代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

char T[200010];
int dp[200010],next[200010],n;

void getnext(){
    int i = 0, j = -1;
    next[0] = -1;
    while(i < n){
        if(j == -1 || T[i] == T[j]){
            i++, j++;
            next[i] = j;
        }
        else j = next[j];
    }
    return;
}

int main(){
    int cas; cin >> cas;
    while(cas--){
        cin >> n;
        cin >> T;
        getnext();
        memset(dp, 0, sizeof(dp));
        int sum = 0;
        for(int i=1; i<=n; i++){
            dp[i] = dp[next[i]] + 1;
            sum = (sum + dp[i]) % 10007;
        }
        cout << sum << endl;
    }
    //system("pause");
    return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值