HDU 3336

 思路:KMP,但要对其进行变形,当找到失败位置时,要继续考察该位置,一直向前找到字符串首不能再向前找,因为我们不只要计算该子串本身,我们还要计算该子串包含的其他子串,因为这些子串都是原串的子串,这是显然的。


#include<stdio.h>
#include<string.h>
int fail[200005];
int sum[200005]; 
char str[200005]; 
int T, m, max;  
void getfail()
{
    fail[0] = -1;
    int i, j, temp; 
    for(i = 1, j = -1; i < m; i ++)
    {
        while(j >= 0 && str[j + 1] != str[i])
        {
            j = fail[j]; 
        }
        if(str[j + 1] == str[i])
            j ++; 
        fail[i] = j;
        if(j >= 0)
        {
            sum[j] ++; 
            if(max < j)
                max = j; 
            temp = j; 
            while(temp >= 0)
            {
                temp = fail[temp]; 
                sum[temp] ++; 
            }
        }
    }
}
    int main(int argc, char const *argv[]) 
    {
        int i, cnt; 
        scanf("%d", &T); 
        while(T--)
        {
            memset(str, 0, sizeof(str)); 
            memset(sum, 0, sizeof(sum)); 
            scanf("%d", &m); 
            cnt = m % 10007; 
            max = 0; 
            getchar(); 
            fgets(str, m+1,stdin);  
            getfail(); 
            for(i = 0; i <= max; i ++)
            {
                /* printf("OK\n"); */
                sum[i] %= 10007; 
                cnt += sum[i]; 
                cnt %= 10007; 
            }
            printf("%d\n", cnt);
        }
        return 0; 
    }


转载于:https://www.cnblogs.com/wangzhili/p/3950336.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值