题目
又到了一年 5.20!牛牛准备了一个字符串 S,里面全都是由 '5'、'2' 和 '0' 组成,但有的数字被油污染了,看不清,以 '?' 表示。
如果把这些被油污染的部分换成 '5'、'2' 和 '0',在所有可能的字符串中,位置不同的为 "520" 的子序列共有多少个?
将答案模 998244353 返回。
解题思路
动态规划:
使用 表示前
个字符中 '5' 的个数。
使用 表示前
个字符中,位置不同的为 "52" 的子序列的总个数。
使用 表示前
个字符中,位置不同的为 "520" 的子序列的总个数。
状态转移方程:
- 当
时,
,否则
。
- 当
时,当前的字符 '2' 可以和前
个字符中的
个 '5' 组成
个 "52" 子序列。
所以,。
- 当
时,当前的字符 '0' 可以和前
个字符中的
个 "52" 子序列组成
个 "520" 子序列。
所以,。
- 当
时,
如果当前的是 '0',那么
;
如果当前的是 '2',那么
;
如果当前的是 '5',那么
。
此时,时间复杂度 ,空间复杂度
。
为字符串
的长度。
根据上面的状态转移方程,可以看出 、
和
只与它们的前一个状态相关。
所以,可以对上面的 dp 进行空间上的优化。代码如下。
此时空间复杂度为 。
C++代码
class Solution {
public:
/**
* 寻找所有的 520 子序列
* @param S string字符串 牛牛准备的数字字符串
* @return int整型
*/
int findOccurrences(string S) {
// write code here
const int mod = 998244353;
int f[3] = {0};
for(int i=0; i<S.size(); ++i){
if(S[i]=='5')
f[0] += 1;
else if(S[i]=='2')
f[1] += f[0];
else if(S[i]=='0')
f[2] += f[1];
else{
f[2] += f[1];
f[1] += f[0];
f[0] += 1;
}
f[0] %= mod;
f[1] %= mod;
f[2] %= mod;
}
return f[2];
}
}; 
京公网安备 11010502036488号