小天的子序列(字符串、组合数、打表)

链接:https://ac.nowcoder.com/acm/contest/72041/D
来源:牛客网

小冰老是搞不清楚子串和子序列的区别,小天想要帮助小冰区分子串和子序列,小天告诉小冰,子串是连续的,子序列不一定连续,在一个字符串中,如果确定了子串的首和尾,那么子串就确定了。而子序列却不一定。
小冰在小天的帮助下,终于学会了。但是现在她遇到了一个难题,想请你帮助她解决一下。
小冰给你一个字符串,mm 次询问,每次询问字符串中有多少个以\(ch_1\)开头,以\(ch_2\)结尾的长为 \(len\)的子序列。

  • 题目中的字符均为小写字母。
  • 题目所求子序列不要求本质不同。

答案对 998244353998244353 取模。
输入描述:
第一行一个正整数\((1\leq n\le 500)\)表示字符串的长度。

第二行一个字符串\(s\)

第三行一个正整数\((1\leq m\leq 10^5)\)表示询问次数。

接下来\(m\)行,每行两个字符\(ch_1,ch_2\)和一个正整数\((2\leq len\leq n)len\)描述一个询问。
输出描述:
\(m\)行,每行一个整数表示询问的子序列数量。

示例1
输入
9
abcxayidy
2
x y 4
x y 2
输出
6
2

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
char s[510];
int n;
int f[26][26][510];
int C[510][510];
int main(){
	scanf("%d",&n);
    scanf("%s", s+1);
    for(int i=0;i<=n;i++){
    	C[i][0]=1;
		for(int j=1;j<=i;j++){
			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			for(int k=0;k<=j-i-1;k++){
				f[s[i]-'a'][s[j]-'a'][k+2]=(f[s[i]-'a'][s[j]-'a'][k+2]+C[j-i-1][k])%mod;
			}
		}
	}
	int t;
	cin>>t;
	while(t--){
		char x[5],y[5];int z;
        scanf("%s%s%d",x,y,&z);
        printf("%d\n", f[x[0]-'a'][y[0]-'a'][z]);
	}
}
posted @ 2023-12-16 21:58  lipu123  阅读(52)  评论(0)    收藏  举报