题目大意:
给定一个序列s,求【前缀是nunhehheh后缀是>=1个a】的子序列个数
题目思路:
定义dp[i][j]为s序列前i个字符与nunhehheh匹配j个字符的个数
预处理出每个i后边有多少个a,用数组suf表示
对于每个dp[i][8]成2的suf[i]幂次方
重点解释一下为什么是dp[i][8]而不是dp[i][9]
--因为前缀是以h结尾,每次匹配到h时我们对答案加上dp[i][8]*2^suf[i]
--如果是dp[i][9]的话,会重复加上之前我们计算过的
代码:
LL P[N], dp[N][20], suf[N];
char s[N], p[11] = "@nunhehheh";
inline void solve()
{
char ch = getchar();
scanf("%s", s + 1);
memset(dp, 0, sizeof dp);
memset(suf, 0, sizeof suf);
int len = strlen(s + 1);
for (int i = len; i >= 0; i -- )
{
dp[i][0] = 1;
suf[i] = (suf[i + 1] + (s[i] == 'a')) % mod;
}
for (int i = 1; i <= len; i ++ )
{
for (int j = 1; j <= 8; j ++ )
{
if (s[i] == p[j]) dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
else dp[i][j] = dp[i - 1][j];
}
}
LL ans = 0;
for (int i = 9; i <= len; i ++ )
{
if (s[i] == 'h')
{
ans += dp[i][8] * (P[suf[i]] - 1) % mod;
ans %= mod;
}
}
printf("%lld\n", ans);
}
int main()
{
int T; scanf("%d", &T);
P[0] = 1;
for (int i = 1; i <= N; i ++ )
P[i] = P[i - 1] * 2 % mod;
while (T -- )
{
solve();
}
return 0;
}