牛客——躲藏
题目描述
XHRlyb和她的小伙伴Cwbc在玩捉迷藏游戏。
Cwbc藏在多个不区分大小写的字符串中。
好奇的XHRlyb想知道,在每个字符串中Cwbc作为子序列分别出现了多少次。
由于Cwbc可能出现的次数过多,你只需要输出每个答案对2000120420010122取模后的结果。
聪明的你在仔细阅读题目后,一定可以顺利的解决这个问题!
输入描述
输入数据有多行,每行有一个字符串。
输出描述
输出数据应有多行,每行表示一个答案取模后的结果。
示例1
输入
Cwbc
输出
1
说明
Cwbc作为子序列仅出现了1次。
示例2
输入
acdcecfwgwhwibjbkblcmcnco
输出
81
说明
Cwbc作为子序列出现了34=81次。
题目分析
这题很明显是动态规划的题目,dp[i][j], 表示前 i 个字符中匹配的 j 的个数,即dp[i][1]表示前 i 个字符中字母‘c’匹配的个数。那么就可以列出状态转移方程
dp[i][1] = (dp[i][1] + (s[i] == ‘c’ )) % mod;
dp[i][2] = (dp[i][2] + (s[i] == ‘w’) * dp[i - 1][1]) % mod;
(这里乘以dp[i - 1][1]是因为‘w’ 的匹配数是由‘c’决定,下面同理 )
dp[i][3] = (dp[i][3] + (s[i] == ‘b’ )* dp[i - 1][2]) % mod;
dp[i][4] = (dp[i][4] + (s[i] == ‘c’)* dp[i - 1][3]) % mod;
但是这一题开二维数组会被卡空间,所以需要降维,由于当前的状态只与前一个状态有关,那么就可以删除第一维,这样就变成:
dp[1] = (dp[1] + (s[i] == ‘c’ )) % mod;
dp[2] = (dp[2] + (s[i] == ‘w’ )* dp[1]) % mod;
dp[3] = (dp[3] + (s[i] == ‘b’ ) * dp[2]) % mod;
dp[4] = (dp[4] + (s[i] == ‘c’) * dp[3]) % mod;
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const ll mod = 2000120420010122;
char s[1000005];
ll dp[5];
int main(){
while(cin >> s){
int l = strlen(s);
memset(dp, 0, sizeof(dp));
for (int i = 0; i < l; i++)
if (s[i] >= 'A' && s[i] <= 'Z')
s[i] = s[i] + 32;
for (int i = 0; i < l; i++){
if (s[i] == 'c')
dp[1] = (dp[1] + 1) % mod;
else
dp[1] = dp[1] % mod;
if (s[i] == 'w')
dp[2] = (dp[2] + 1 * dp[1]) % mod;
else
dp[2] = dp[2] % mod;
if (s[i] == 'b')
dp[3] = (dp[3] + 1 * dp[2]) % mod;
else
dp[3] = dp[3] % mod;
if (s[i] == 'c')
dp[4] = (dp[4] + 1 * dp[3]) % mod;
else
dp[4] = dp[4] % mod;
}
cout << dp[4] << endl;
}
return 0;
}