小天的子序列(字符串、组合数、打表)
链接: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]);
}
}