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

    题目链接

    Problem Description
    Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,which have a big secret.SF is interested in this secret and ask VS how to get it.There are the things that VS tell:
    Suffix(S2,i) = S2[i...len].Ni is the times that Suffix(S2,i) occurs in S1 and Li is the length of Suffix(S2,i).Then the secret is the sum of the product of Ni and Li.
    Now SF wants you to help him find the secret.The answer may be very large, so the answer should mod 1000000007.

    Input
    Input contains multiple cases.
    The first line contains an integer T,the number of cases.Then following T cases.
    Each test case contains two lines.The first line contains a string S1.The second line contains a string S2.
    1<=T<=10.1<=|S1|,|S2|<=1e6.S1 and S2 only consist of lowercase ,uppercase letter.

    Output
    For each test case,output a single line containing a integer,the answer of test case.
    The answer may be very large, so the answer should mod 1e9+7.

    Sample Input
    2
    aaaaa
    aa
    abababab
    aba

    Sample Output
    13
    19

    Hint
    case 2:
    Suffix(S2,1) = "aba",
    Suffix(S2,2) = "ba",
    Suffix(S2,3) = "a".
    N1 = 3,
    N2 = 3,
    N3 = 4.
    L1 = 3,
    L2 = 2,
    L3 = 1.
    ans = (33+32+4*1)%1000000007.

    题意:

    给定两个字符串,一个匹配串一个模式串,我们的目的是在匹配串中找出所有的能够以模式串为前缀的串的长度,将长度累加求得最终的长度。

    分析:
    这道题最核心的思想就是模式匹配,但是又有一点点的改进。

    我们之大模式匹配在找到一个匹配串时候就直接逃过了,这样的话会减少我们中间查找的匹配串,所以我们将模式串中每一个字符上一次出现的位置记录下来,这样的话就能很好的解决这个问题。

    记录模式串的每个前缀(即反转前的后缀)出现的次数,考虑kmp的next数组,f[i]代表1~i包含1~f[i],那么ans[f[i]]+=ans[i];

    代码:

    #include <cstdio>
    #include <iostream>
    #include<string.h>
    #include <algorithm>
    #define ll long long
    using namespace std;
    const int N=1e6+10;
    const int MOD=1e9+7;
    char a[N],b[N];
    int f[N];
    ll ans[N];
    void get_next()///获取相同的字符上一次出现的位置
    {
        int m=strlen(b);
        f[0]=f[1]=0;
        for(int i=1; i<m; i++)
        {
            int j=f[i];
            while(j&&b[i]!=b[j]) j=f[j];
            f[i+1]=b[i]==b[j]?j+1:0;
        }
    }
    void kmp_count()///模式匹配
    {
        int n=strlen(a),m=strlen(b);
        int j=0;
        for(int i=0; i<n; i++)
        {
            while(j&&b[j]!=a[i]) j=f[j];
            if(b[j]==a[i]) j++;
            ans[j]++;
            if(j==m)
            {
                j=f[j];
                if(j>m) j=0;
            }
        }
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s%s",a,b);
            reverse(b,b+strlen(b));
            reverse(a,a+strlen(a));
            memset(ans,0,sizeof(ans));
            get_next();
            kmp_count();
            int m=strlen(b);
            for(int i=m; i>=1; i--)
                ans[f[i]]+=ans[i];
            ll sum=0;
            for(ll i=1; i<=m; i++)
            {
                sum=(sum+i*ans[i])%MOD;
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
    
  • 相关阅读:
    详解JVM中的内存模型是什么?
    【亲测】手把手教你如何破解pycharm(附安装包和破解文件)
    Spring实战第4版PDF下载含源码
    Tomcat的基本使用及相关知识的概述(超详细版)
    JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析 !
    详解JVM中的五大内存区域
    [Django][python][工具]阿里云平台短信验证功能
    [数据分析][评价方法]打分式评价-信息熵理论与熵权法
    [工具]用OmniGraffle 五步绘制流程图
    [操作系统]设备分配中的数据结构:设备控制表(DCT)、控制器控制表(COCT)、通道控制表(CHCT)和系统设备表(SDT)
  • 原文地址:https://www.cnblogs.com/cmmdc/p/7397957.html
Copyright © 2011-2022 走看看