考虑dp[i][j]:T串 i-j 区间匹配,的方案数。
由于序列是不断增长,最终序列只要前缀包含T即可,所以我们把T串变成T***(后面加*知道与S串相同长度)
那结果就是 .
我们枚举S串,一位一位更新区间DP。
由于每一位S会让目标串长度加一,所以枚举的Si,中的i就是区间DP的长度。
所以二维区间DP就可以维护更新了。
考虑更新:
我们知道S串1 - i-1,构成T串的所有方案。
只需要看S[i]与T[l],t[r]的关系即可。
如果S[i]等于T[l]表示,S[i]可以加在 T[l+1,r]前面,构成T[l,r].
同理如果S[i]等于T[r]表示,S[i]可以加在T[l,r-1]后面,构成T[l,r]
T[m+1,n]中间的字符是任意字符,即任何S都能匹配。(相当于先放后面再放前面)
比如样例1:
S:abab
T:ba**
S的第一个字符可以组成:T[2,2],T[3,3],T[4,4]
S的前两个个字符组成:T[1,2],T[2,3],T[3,4]
……
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 3e3+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,-1,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
const int mod= 998244353;
ll dp[M][M];
char s[M],t[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>(s+1)>>(t+1);
int n=strlen(s+1),m=strlen(t+1);
for(int i=1;i<=n+1;i++)dp[i][i-1]=1;
ll ans=0;
/*
S:abab
T:ba**
*/
for(int i=1;i<=n;i++)//枚举S
{
for(int l=1;l+i-1<=n;l++)
{
int r=l+i-1;
if(s[i]==t[l]||l>m)dp[l][r]+=dp[l+1][r];
if(s[i]==t[r]||r>m)dp[l][r]+=dp[l][r-1];
dp[l][r]%=mod;
}
}
for(int i=m;i<=n;i++)ans+=dp[1][i],ans%=mod;
cout<<ans<<endl;
return 0;
}