题目
参考
题意:给定s串和t串,长度分别为n和m(m<=n<=3000);每次取出s串并添加到A串(初始为空串),可以添加在头部,也可以添加在尾部。最多可以操作n次,问可以构造多少个A串,使得其前缀包含t串。
思路:区间dp。定义
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示包含子串
t
[
i
.
.
j
]
t[i..j]
t[i..j]的可达方案数,答案为
d
p
[
1
]
[
m
]
+
d
p
[
1
]
[
m
+
1
]
+
.
.
+
d
p
[
1
]
[
n
]
dp[1][m]+dp[1][m+1]+..+dp[1][n]
dp[1][m]+dp[1][m+1]+..+dp[1][n]。转移时注意边界。
处理关键点:把s串和t串都看出长度为n的串。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 998244353;
const int maxn = 3010;
char s[maxn],t[maxn];
int n,m;
ll dp[maxn][maxn];
int main() {
scanf("%s%s",s+1,t+1);
n = strlen(s+1);
m = strlen(t+1);
for(int i = 1;i <= m;++i)
if(t[i] == s[1])
dp[i][i] = 2;
for(int i = m+1;i <= n;++i)
dp[i][i] = 2;//越界特判
for(int len = 2;len <= n;++len) {
char ch = s[len];
for(int l = 1,r;l+len-1 <= n;++l) {
r = l+len-1;
if(l > m || ch == t[l])
dp[l][r] = (dp[l][r]+dp[l+1][r])%mod;
if(r > m || ch == t[r])
dp[l][r] = (dp[l][r]+dp[l][r-1])%mod;
}
}
ll ans = 0;
for(int i = m;i <= n;++i)
ans = (ans + dp[1][i])%mod;
printf("%lld\n",ans);
}