zoukankan      html  css  js  c++  java
  • HDU 6153 A Secret 套路,求解前缀在本串中出现的次数

    http://acm.hdu.edu.cn/showproblem.php?pid=6153

    首先相当于翻转两个串,然后求s2前缀在s1中出现的次数。

    这是一个套路啦

    首先把两个串结合起来,中间加一个'%'之类的分割

    设dp[i]表示前缀1---i在本串中的出现次数和

    那么从后开始dp,所有dp值一开始都是1,表示前缀出现了一次,就是自己本身。

    转移,设当前去到第i位,则dp[next[i + 1] - 1] += dp[i]

    就是ABACABA这样,已经知道了ABACABA出现了一次,然后前后缀ABA和ABA重复出现,那么dp[3]肯定能够加上dp[7]的,dp[7]包含了dp[7]个"ABA",就这个意思。

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 2e6 + 20;
    int nextliu[maxn], dp[maxn];
    char str[maxn], sub[maxn];
    void get_next (char str[], int nextliu[], int lenstr) {
        int i = 1, j = 0;
        nextliu[1] = 0;
        while (i <= lenstr) {
            if (j == 0 || str[i] == str[j]) {
                nextliu[++i] = ++j;
            } else j = nextliu[j];
        }
        return ;
    
    }
    const int MOD = 1e9 + 7;
    int dp2[maxn];
    void work() {
        scanf("%s%s", str + 1, sub + 1);
        int lenstr = strlen(str + 1), lensub = strlen(sub + 1);
        reverse(str + 1, str + 1 + lenstr);
        reverse(sub + 1, sub + 1 + lensub);
        int to = lensub + 1;
        sub[to++] = '$';
        for (int i = 1; i <= lenstr; ++i) sub[to++] = str[i];
        sub[to] = '';
        to--;
        for (int i = 1; i <= lensub; ++i) dp[i] = 0;
        for (int i = lensub + 2; i <= to; ++i) dp[i] = 1;
        get_next(sub, nextliu, to);
        for (int i = to; i >= 1; --i) {
            int t = nextliu[i + 1] - 1;
            dp[t] += dp[i];
            dp[t] %= MOD;
        }
    //    printf("%d
    ", dp[2] - dp2[2]);
        LL ans = 0;
        for (int i = 1; i <= lensub; ++i) {
            ans += 1LL * i * dp[i] % MOD;
            ans %= MOD;
        }
        printf("%I64d
    ", ans);
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        int t;
        scanf("%d", &t);
        while (t--) work();
        return 0;
    }
    View Code

    其实也可以用后缀数组 + dp搞,不过TLE了,应该要用DC3,不去搞了

    http://codeforces.com/contest/432/problem/D 

    http://acm.gdufe.edu.cn/Problem/read/id/1338

  • 相关阅读:
    js克隆
    一些笔试题
    js的严谨模式
    Docker之Compose服务编排
    最近5年183个Java面试问题列表及答案[最全]
    Rancher概述
    迭代器和生成器
    Prometheus 安装
    Prometheus 介绍
    装饰器函数
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7398502.html
Copyright © 2011-2022 走看看