zoukankan      html  css  js  c++  java
  • HDU 6153 A Secret ( KMP&&DP || 拓展KMP )

    题意 : 给出两个字符串,现在需要求一个和sum,考虑第二个字符串的所有后缀,每个后缀对于这个sum的贡献是这个后缀在第一个字符串出现的次数*后缀的长度,最后输出的答案应当是 sum % 1e9+7

    分析 :

    有两种做法,如果会拓展KMP的话可以说这就是一道模板题了,拓展KMP专门就是找最长公共前缀的长度,首先将给出的两个字符串双双反转,用模式串去跟主串跑一遍拓展KMP,得到 extend 数组,然后只要遍历一遍 extend 数组,每一个 extend[i] 表示模式串里面前 extend[i] 个前缀都出现过了,因此贡献应该是 1+2+...+extend[i],是等差数列

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define LL long long
    const int maxn = 1e6 + 10;
    const int  mod = 1e9 + 7;
    int next[maxn], extend[maxn], moL, strL;
    char mo[maxn], S[maxn];
    LL sum[maxn];
    void GetNext()
    {
        next[0] = moL;
        int a, p;
        for (int i = 1, j = -1; i < moL; i++, j--){
            if (j < 0 || i + next[i - a] >= p){
                if (j < 0) p = i, j = 0;
    
                while (p < moL && mo[p] == mo[j]) p++, j++;
    
                next[i] = j;
                a = i;
            } else next[i] = next[i - a];
        }
    }
    
    void GetExtend()
    {
        GetNext();
        int a;
        int p;
        for (int i = 0, j = -1; i < strL; i++, j--){
            if (j < 0 || i + next[i - a] >= p){
                if (j < 0) p = i, j = 0;
    
                while (p < strL && j < moL && S[p] ==  mo[j])
                    p++, j++;
    
                extend[i] = j;
                a = i;
            } else extend[i] = next[i - a];
        }
    }
    
    inline void PrintAns()
    {
        GetExtend();
        LL ans = 0;
        for(int i=0; i<strL; i++){
            if(extend[i]){
                LL tmp = extend[i];
                tmp = (tmp+1)*tmp/2;
                ans = (ans%mod + tmp%mod)%mod;
            }
        }
        printf("%lld
    ", ans);
    }
    int main()
    {
        int nCase;
        scanf("%d", &nCase);
        while(nCase--){
            scanf("%s %s", S, mo);
            strL = strlen(S);
            moL  = strlen(mo);
            std::reverse(S, S+strL);
            std::reverse(mo, mo+moL);
            PrintAns();
        }
        return 0;
    }
    View Code

    而KMP做法就是用到了NEXT数组的性质,在解决这题之前or后可以看看这道非常相似的题 ==> 51Nod 1277

    只要理解了51Nod 1277的kmp+dp解法,这道题直接效仿即可,关于 51Nod 1277 的题解报告点这里 or 百度

    #include<bits/stdc++.h>
    using namespace std;
    const int mod = 1e9 + 7;
    const int maxn = 1e6 + 10;
    int Next[maxn], moL, strL;
    long long d[maxn];
    char mo[maxn], str[maxn];
    inline void GetNext()
    {
        int i = 0, j = -1;
        Next[i] = j;
        while(i < moL){
            while(j!=-1 && mo[j]!=mo[i]) j = Next[j];
            Next[++i] = ++j;
        }
    }
    inline void Kmp()
    {
        memset(d, 0, sizeof(d));
        int i = 0, j = 0;
        while(i < strL){
            while(j!=-1 && mo[j]!=str[i]) j = Next[j];
            i++, j++, d[j]++;
            if(j == moL) j = Next[j];
        }
    }
    inline void PrintAns()
    {
        GetNext(); Kmp();
        long long sum = 0;
        for(int i=moL; i>0; i--){
            d[Next[i]] += d[i];
            sum = (sum + d[i]*i) % mod;
        }
        printf("%I64d
    ", sum);
    }
    int main(void)
    {
        int nCase;
        scanf("%d", &nCase);
        while(nCase--){
            scanf("%s %s", str, mo);
            moL = strlen(mo);
            strL = strlen(str);
            std::reverse(str, str+strL);
            std::reverse(mo , mo+moL);
            PrintAns();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    javascript小测试
    js设计模式--策略模式
    js设计模式--迭代器模式
    面试题自我解析
    js设计模式--工厂模式
    js设计模式--单体模式
    Python学习一:Python简介
    Angularjs学习笔记《一》
    实现字体最小,不是默认的12px,可以在视觉上最小达到6px
    css3 transform之后,图片的清晰度下降解决方式
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7577306.html
Copyright © 2011-2022 走看看