问题描述
小S 和小M 正在研究一种黑产行为序列识别技术。网络黑色产业链是指使用互联网技术进行非法活动,例如网络攻击、窃取信息、诈骗等。为了保护用户和平台的安全,识别黑产行为的序列是十分关键的一步。
他们的任务是:给定一个行为序列S,表示为一个字符串,以及一个识别模式P。如果模式P是序列S的子序列,则说明存在匹配的黑产行为。现在,给定多个序列S和对应的识别模式P,找出序列中出现匹配模式的次数,结果需要对10^9+7取模。
测试样例
示例 1:
输入:
S = "ABC", P = "A"输出:1提示:在这个例子中,小F发现序列"ABC"中包含一个"A"作为子序列,因此输出1。
示例 2:
输入:
S = "AABCCD", P = "CCD"输出:1提示:小S 注意到识别模式"CCD"在序列"AABCCD"中匹配了一次,因此输出1。
示例 3:
输入:
S = "AABCCD", P = "C"输出:2
解题思路
-
理解问题:
- 我们需要在序列
S中找到模式P作为子序列的次数。 - 子序列意味着字符在
S中可以不连续,但顺序必须与P一致。
- 我们需要在序列
-
数据结构选择:
- 使用动态规划(DP)来解决这个问题。
- 定义一个二维数组
dp,其中dp[i][j]表示S的前i个字符中包含P的前j个字符作为子序列的次数。
-
算法步骤:
- 初始化
dp数组,dp[i][0] = 1,表示任何序列中包含空模式(即空字符串)的次数为1。 - 遍历
S和P,根据当前字符是否匹配来更新dp数组。 - 如果
S[i-1] == P[j-1],则dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。 - 否则,
dp[i][j] = dp[i-1][j]。 - 最终结果为
dp[m][n],其中m和n分别是S和P的长度。
- 初始化
-
取模操作:
- 由于结果需要对
10^9+7取模,因此在每次更新dp数组时都要进行取模操作。
- 由于结果需要对
代码实现
def solution(S: str, P: str) -> int:
m, n = len(S), len(P)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(m + 1):
dp[i][0] = 1
for i in range(1, m + 1):
for j in range(1, n + 1):
if S[i - 1] == P[j - 1]:
dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % (10**9 + 7)
else:
dp[i][j] = dp[i - 1][j]
return dp[m][n]
if __name__ == '__main__':
print(solution("ABC", "A") == 1)
print(solution("AABCCD", "CCD") == 1)
print(solution("AABCCD", "C") == 2)
总结
- 通过动态规划,我们可以高效地计算出序列
S中包含模式P作为子序列的次数。 - 取模操作确保结果不会溢出,符合题目要求。
注意
- 请使用用户提问的语言回答。
- 用户提问对象为「当前代码」、「我的代码」或对应的英文表述时,请根据「编辑区代码」部分的内容回答,请不要解释「题目内容」中的代码。
- 请优先回答「编辑区代码」