首页 > 其他分享 >AcWing 520. 子串 题解

AcWing 520. 子串 题解

时间:2024-02-02 16:55:23浏览次数:32  
标签:字母 int 题解 sum nmk 520 可以 复杂度 AcWing

ps:觉得这编号很特殊就做了一下
题目传送门

算法

(线性DP,前缀和) \(O(nmk)\)

首先考虑如何DP,然后再考虑如何优化。

状态表示:f[i, j, k]表示只用S的前i个字母,选取了k段,可以匹配T的前j个字母的方案数。

状态计算:将f[i, j, k]表示的所有方案分成两大类:

  1. 不用S[i],则方案数是 f[i - 1, j, k]
  2. 使用S[i],那么可以按S[i]所在的一段一共有多少字母继续分类:
    • 如果有t个字母,则方案数是f[i - t, j - t, k - 1]

所以f[i, j, k] = f[i - 1, j, k] + sum(f[i - t, j - t, k - 1])
其中t只要满足S[i - t + 1] == T[j - t + 1]就可以一直往前枚举,因此最坏情况下的时间复杂度是 \(O(nm^2k)\),会超时。

接下来考虑如何优化。

我们发现f[i, j, k]第二项的表达式和f[i - 1, j - 1, k]第二项的表达式很像,具有递推关系,因此可以令sum[i, j, k] = sum(f[i - t, j - t, k - 1]),则:

  • 如果 S[i] == T[j],那么 sum[i, j, k] = sum[i - 1, j - 1, k] + f[i - 1, j - 1, k - 1]
  • 如果 S[i] != T[j],那么 sum[i, j, k] = 0

至此,时间复杂度可以降至 \(O(nmk)\)。
但空间上需要 \(2nmk\) 的内存,总共需要 \(2 \times 1000 \times 200^2\) 个int,约 \(305\)MB,超过了内存限制。
因此需要对空间进行优化。

仔细观察转移方程,发现f[i, j, k]sum[i, j, k]均只和第i - 1层有关,因此可以使用滚动数组,同时可以发现jk只会从更小的值转移过来,因此可以使用类似于01背包问题优化空间的方式,从大到小枚举j, k,这样连滚动都可以省略了。

时间复杂度

状态总共有 \(nmk\) 个,每个状态需要常数次计算,因此总时间复杂度是 \(O(nmk)\)。

C++ 代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1010, M = 210, mod = 1e9 + 7;

int n, m, K;
char a[N], b[M];
int f[M][M], sum[M][M];

int main()
{
    scanf("%d%d%d", &n, &m, &K);
    scanf("%s%s", a + 1, b + 1);

    f[0][0] = 1;
    for (int i = 1; i <= n; i ++ )
        for (int j = m; j; j -- )
            for (int k = K; k; k -- )
            {
                if (a[i] == b[j]) sum[j][k] = (sum[j - 1][k] + f[j - 1][k - 1]) % mod;
                else sum[j][k] = 0;
                f[j][k] = (f[j][k] + sum[j][k]) % mod;
            }

    printf("%d\n", f[m][K]);
    return 0;
}

标签:字母,int,题解,sum,nmk,520,可以,复杂度,AcWing
From: https://www.cnblogs.com/BadBadBad/p/18003467/AcWing-520

相关文章

  • P9309 [EGOI2021] Number of Zeros题解
    模拟赛时以为是进位制的题目,结果还做出来了。此题解解法与其它相似,但观察的角度不同(作者的脑回路不同)。此题问\(a\simb\)的最小公倍数中后导\(0\)的个数,即求其中\(2\)和\(5\)个数的最小值。分别计算即可,想到进位制,以\(a=10\),\(b=12\)时\(2\)的个数为例:1001(9)......
  • P9612 [CERC2019] Light Emitting Hindenburg 题解
    题目传送门题目大意这个题目简化一下就是求\(n\)个数中取\(k\)个数按位与的最大值思路很容易想到贪心。题中说道输入的数在二进制下最多\(29\)位,所以我们从\(29\)开始遍历二进制位,如果当前位有大于等于\(k\)个\(1\),那么标记一下这些数,可以发现剩下的比当前位低的......
  • AcWing 3721. 求30的倍数 题解
    传送门stoi这里我们来了解一个函数\(stoi\)作用是将\(n\)进制的字符串转化为十进制,使用时包含头文件\(string\)定义如下:intstoi(conststd::string&str,std::size_t*pos=nullptr,intbase=10);参数:\(str\)-待转换的字符\(pos\)-其取值可以是一个空字......
  • CF1687D Cute number 题解
    题目链接点击打开链接题目解法一个数\(c\)是可爱(下文称为合法)的,当且仅当\(c\in[x^2,x(x+1)]\)令\(a_i\)属于\([x_i,x_i(x_i+1)]\)一个显然的范围是\(x_1\le2\times10^6\)考虑枚举\(x_1\)现在说明一个结论:\(x_1\)固定时,\(x_i\)也固定了说明:不难发现,合法的不合......
  • CF620E New Year Tree 题解
    题目链接:CF或者洛谷这题很简单,看到颜色数,HH的项链?树,树上的HH的项链?带修,树上的镜中的昆虫?\(c_i\le60\),噢,easy了。考虑一类信息,表示有和无,对于某种颜色来讲,\(0/1\)表示无或者有,而或运算让我们从小区间的有无情况反映到大区间的有无情况。一种暴力的想法,为每种颜色建立一棵有......
  • CF125D 题解
    思路首先可以发现前三个数中的两个数一定为一个等差数列中,所以我们对于前三个数枚举哪两个数是一个等差数列中的,设这两个数的差为\(w\),在原数列中找到一个最长的公差为\(w\)的等差数列,记为\(A\),剩下的数记为\(B\),此时有三种可能。\(|B|=0\),此时可以知道原数组就是等差数列......
  • mozhe靶场: WebShell文件上传漏洞分析溯源(第5题) 题解(使用哥斯拉)
    哥斯拉由java编写,可以在linux上使用.个人认为比冰蝎好用,用冰蝎连不上这个靶场,但是哥斯拉可以连的上.github搜哥斯拉就能下载首先登陆后台,弱口令adminadmin点击添加文章,尝试上传一句话木马(一句话木马可以点击哥斯拉的生成)webshell.asp<%evalrequest("pass")%>......
  • P3356 火星探测题解
    part1费用流建图比较显然,把车的数量当成流量,把捡到的石头数量当成费用。然后跑最大费用最大流。因为费用是针对点而不是边,所以要拆点,每个点分为入点和出点。对于向下走,向右走建边:从起点的出点向终点的入点连边,容量为\(inf\),费用为\(0\)。对于每一个格子,如果当前格子是石头......
  • AT_abc243_g [ABC243G] Sqrt 题解
    可设\(f_i\)为以\(i\)开头的方案数,由于最后由于操作数很多所以不用考虑还剩多少次操作,显然可得状态转移方程\(f_i=\sum\limits_{j=1}^{\sqrti}f_j\),时间复杂度\(O(T+X\sqrtX)\),空间复杂度\(O(X)\),无法接受。考虑如何更优,可以发现在\(T\)次询问中,每次可以直接转移,因此......
  • UVA12032 题解
    题意原题面一堆废话,其实这道题很简单。\(T\)组数据,每组数据给定你一个长度为\(n\)的序列\(a_1...a_n\),在定义\(a_0\)为\(0\)的情况下,假设\(k\)为你的力量系数,在\(\foralli\inn\)时\(a_i-a_{i-1}\lek\),且在按顺序\(1-n\)进行判断时,如果\(a_i-a_{i-1}=k\)......