题解:AtCoder AT_awc0028_e Counting Subsequences

【题目来源】

AtCoder:E - Counting Subsequences

【题目描述】

Takahashi is researching algorithms related to sequences. Today, he is working on a subsequence matching problem in sequences.
高桥正在研究与序列相关的算法。今天,他正在研究序列中的子序列匹配问题。

You are given a sequence \(A = (A_1, A_2, \ldots, A_N)\) of length \(N\) and a pattern sequence \(P = (P_1, P_2, \ldots, P_K)\) of length \(K\). Each element of the sequence \(A\) and the pattern sequence \(P\) is a positive integer.
给定一个长度为 \(N\) 的序列 \(A = (A_1, A_2, \ldots, A_N)\) 和一个长度为 \(K\) 的模式序列 \(P = (P_1, P_2, \ldots, P_K)\)。序列 \(A\) 和模式序列 \(P\) 的每个元素都是正整数。

Takahashi wants to find the number of ways to choose \(K\) distinct positions from the sequence \(A\) such that the subsequence formed by those positions, preserving the original order, matches the pattern sequence \(P\).
高桥希望找出从序列 \(A\) 中选择 \(K\) 个不同位置的方法数,使得这些位置构成的子序列(保持原始顺序)与模式序列 \(P\) 匹配。

More precisely, find the number of index tuples \((i_1, i_2, \ldots, i_K)\) satisfying \(1 \leq i_1 < i_2 < \cdots < i_K \leq N\) such that \(A_{i_j} = P_j\) holds for all \(j\) \((1 \leq j \leq K)\).
更精确地说,求满足 \(1 \leq i_1 < i_2 < \cdots < i_K \leq N\) 的索引元组 \((i_1, i_2, \ldots, i_K)\) 的数量,使得对所有 \(j\)\(1 \leq j \leq K\))有 \(A_{i_j} = P_j\) 成立。

Note that if the chosen index tuples differ in even one position, they are counted as distinct selections, even if the values of all selected elements are the same.
注意,即使所选的所有元素的值相同,只要所选索引元组中有一个位置不同,它们就被计为不同的选择。

Since the answer can be very large, find it modulo \(10^9 + 7\).
由于答案可能非常大,请对 \(10^9 + 7\) 取模后输出结果。

【输入】

\(N\) \(K\)
\(A_1\) \(A_2\) \(\ldots\) \(A_N\)
\(P_1\) \(P_2\) \(\ldots\) \(P_K\)

  • The first line contains two integers \(N\) and \(K\), separated by a space, representing the length of the sequence \(A\) and the length of the pattern sequence \(P\), respectively.
  • The second line contains the elements \(A_1, A_2, \ldots, A_N\) of the sequence \(A\), separated by spaces.
  • The third line contains the elements \(P_1, P_2, \ldots, P_K\) of the pattern sequence \(P\), separated by spaces.

【输出】

Print on a single line the number of index tuples satisfying the condition, modulo \(10^9 + 7\).

【输入样例】

5 2
1 2 1 2 1
1 2

【输出样例】

3

【核心思想】

  1. 问题分析:给定长度为 \(N\) 的主序列 \(A\) 和长度为 \(K\) 的模式序列 \(P\),求从 \(A\) 中选择 \(K\) 个不同位置构成子序列(保持原顺序)与 \(P\) 匹配的方案数。这是一个二维DP子序列匹配计数问题,类似于LCS(最长公共子序列)的变形。

  2. 算法选择

    • 二维DPdp[i][j] 表示考虑主序列前 \(i\) 个元素,匹配子序列前 \(j\) 个元素的方案数
    • 类似编辑距离:但只考虑删除操作(不选元素)
    • 滚动数组优化:可将空间复杂度优化至 \(O(K)\)
  3. 关键步骤

    • 初始化dp[i][0] = 1(匹配空子序列只有一种方式:什么都不选)
    • 状态转移:遍历主序列每个位置 \(i\) 和子序列每个位置 \(j\)
      • 不选 \(A[i]\)dp[i][j] = dp[i-1][j](继承前 \(i-1\) 个元素的方案数)
      • \(A[i]\)(如果 \(A[i] == P[j]\)):dp[i][j] += dp[i-1][j-1](用 \(A[i]\) 匹配 \(P[j]\)
    • 统计答案dp[N][K] 即为所求
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N \times K)\)
    • 空间复杂度:\(O(N \times K)\),可优化至 \(O(K)\)(滚动数组)
  5. 二维DP子序列匹配的核心思想

    • 状态设计:同时追踪主序列和子序列两个维度
    • 两种选择:每个位置可以选择匹配当前字符或不匹配
    • 字符相等才匹配:只有当 \(A[i] == P[j]\) 时才能进行匹配转移
    • 模数运算:结果对 \(10^9 + 7\) 取模,防止溢出
    • 适用于子序列计数、模式匹配类问题

【解题思路】

【算法标签】

线性DP-一维

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 100005, M = 105, mod = 1e9 + 7;

int n, k;
// a 数组存储主序列
int a[N];
// p 数组存储要匹配的子序列
int p[M];
// dp[i][j] 表示:考虑主序列前 i 个元素,匹配到子序列前 j 个元素的方案数
int dp[N][M];

int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= k; i++)
    {
        cin >> p[i];
    }

    // 初始化:主序列前 i 个元素匹配空子序列的方案数为 1
    for (int i = 0; i <= n; i++)
    {
        dp[i][0] = 1;
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= k; j++)
        {
            // 不选主序列第 i 个元素
            dp[i][j] = dp[i - 1][j];
            // 如果主序列第 i 个元素等于子序列第 j 个元素
            if (a[i] == p[j])
            {
                // 可以选择主序列第 i 个元素来匹配子序列第 j 个元素
                dp[i][j] = (dp[i][j] + dp[i - 1][j - 1]) % mod;
            }
        }
    }

    // 输出主序列前 n 个元素匹配到子序列前 k 个元素的方案数
    cout << dp[n][k] << endl;
    return 0;
}

【运行结果】

5 2
1 2 1 2 1
1 2
3
posted @ 2026-06-15 09:49  团爸讲算法  阅读(8)  评论(0)    收藏  举报