zoukankan      html  css  js  c++  java
  • 2017中国大学生程序设计竞赛

    题目链接: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
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    接口内容小结
    接口的静态方法与私有方法
    接口的默认方法
    发红包O
    抽象
    《大道至简》读后感
    重写
    继承中的二义性问题
    数学应用
    继承
  • 原文地址:https://www.cnblogs.com/spfa/p/7397689.html
Copyright © 2011-2022 走看看