码迷,mamicode.com
首页 > 其他好文 > 详细

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6153 A Secret KMP,思维

时间:2017-08-19 21:13:08      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:大学   show   fail   for   指针   c++   name   pre   max   

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153

题意:给了串s和t,要求每个t的后缀在在s中的出现次数,然后每个次数乘上对应长度求和。

解法:关键在于想到把s和t都翻转之后,把t求next,然后用t去匹配s,在匹配过程中把fail指针跳到的地方加1,但是还没完,最后需要反向遍历第二个串将大串对小串的贡献加上去就可以了。

这道题是很多现场AC的代码是有漏洞的,比如bazbaba,bazbaba这个答案是34,但是很多现场AC的代码会输出31。。。敝队就是这样,然而AC了。。。

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6+7;
const int mod = 1e9+7;
char s[maxn],t[maxn];
int n, m, fail[maxn], cnt[maxn];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%s", s+1);
        scanf("%s", t+1);
        n = strlen(s+1);
        m = strlen(t+1);
        reverse(s+1, s+n+1);
        reverse(t+1, t+m+1);
        int j=0;
        for(int i=2; i<=m; i++){
            while(j>0&&t[i]!=t[j+1]) j=fail[j];
            if(t[i]==t[j+1])j++;
            fail[i]=j;
        }
        memset(cnt, 0, sizeof(cnt));
        j=0;
        for(int i=1; i<=n; i++){
            while(j>0&&t[j+1]!=s[i]) j=fail[j];
            if(t[j+1]==s[i]) j++;
            cnt[j]++;
        }
        for(int i=m; i>=1; i--){
            cnt[fail[i]]+=cnt[i];
        }
        int ans=0;
        for(int i=1; i<=m; i++){
            ans += (LL)cnt[i]*i%mod;
            ans %= mod;
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6153 A Secret KMP,思维

标签:大学   show   fail   for   指针   c++   name   pre   max   

原文地址:http://www.cnblogs.com/spfa/p/7397689.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!