题目链接:Problem - 7131 (hdu.edu.cn)
题目大概意思:给我们一个单词前缀nunhehheh,完整的合法子串需要前缀后面带若干个a(只能是a),数目不能是0,然后给我们一个字符串,问我们该字符串中有多少个满足题意的连续子串。
这道题目我们考虑dp求解,用dp[i][j]表示前i个字符中含有目标子串长度为j的方案数,下面直接进行dp就好,每找到一个合法的完整前缀,只需要乘以其后面a的贡献即可,注意取模。
下面是代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+10,mod=998244353;
ll f[N][10];
//f[i][j]表示前i个字符中目标子串长度为j的方案数
char s[N];
ll qmi(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%s",s+1);
int len=strlen(s+1);
//cnt记录a的个数
ll ans=0,cnt=0;
for(int i=1;i<=len;i++)
{
for(int j=1;j<=9;j++)
f[i][j]=0;
if(s[i]=='a')
cnt++;
}
for(int i=1;i<=len;i++)
{
for(int j=1;j<=9;j++)//不要忘记一开始的赋值
f[i][j]=f[i-1][j];
if(s[i]=='n')
{
f[i][1]=(f[i][1]+1)%mod;
f[i][3]=(f[i][3]+f[i-1][2])%mod;
}
else if(s[i]=='u') f[i][2]=(f[i][2]+f[i-1][1])%mod;
else if(s[i]=='h')
{
f[i][4]=(f[i][4]+f[i-1][3])%mod;
f[i][6]=(f[i][6]+f[i-1][5])%mod;
f[i][7]=(f[i][7]+f[i-1][6])%mod;
f[i][9]=(f[i][9]+f[i-1][8])%mod;
//注意此处f[i][9]有可能小于f[i-1][9]
ans=(ans+((f[i][9]-f[i-1][9]+mod)%mod)*(qmi(2,cnt)-1))%mod;
}
else if(s[i]=='e')
{
f[i][5]=(f[i][5]+f[i-1][4])%mod;
f[i][8]=(f[i][8]+f[i-1][7])%mod;
}
else if(s[i]=='a') cnt--;
}
printf("%lld\n",ans);
}
return 0;
}