(2021ccpc网络赛重赛)Nun Heh Heh Aaaaaaaaaaa(dp)

题目链接: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;
} 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值