Kaavi and Magic Spell - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
我们直接考虑如何构造出来的字符串,这个字符串显然只能每次最左端加或者最右端加入。
对于第一个字符,显然每个位置都够能放置,且有两种方案。接着下一个字符加入它的左端或者右端,依次类推。
令 dp[i][j] 为 s(1)~s(j-i+1) 构造出 t(i)~t(j)的方案数。
(这种思想跟合唱队是同一种区间dp思想,P3205 [HNOI2010]合唱队(区间dp+方案数) - QAQ啥也不会 - 博客园 (cnblogs.com))
对于dp[i][j]的转移方程:
当前s[j-i+1]加入最左边,且s[j-i+1]==t[i]:dp[i][j]=(dp[i][j]+dp[i+1][j])%MOD;
当前s[j-i+1]加入最右边,且s[j-i+1]==t[j]:dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD;
当然显然本题 t 字符串的长度可能会短,所以 s[j-i+1] 加入的位置大于了 t 字符串的长度,显然此时一定是合法的状态
所以dp[i][j]的转移方程便是:
当前s[j-i+1]加入最左边,且s[j-i+1]==t[i] or i>tlen :dp[i][j]=(dp[i][j]+dp[i+1][j])%MOD;
当前s[j-i+1]加入最右边,且s[j-i+1]==t[j] or j>tlen :dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD;
对于dp初始化:
for(int i=1;i<=m;i++) dp[i][i]=2*(s[1]==t[i]);
for(int i=m+1;i<=n;i++) dp[i][i]=2;
最后答案的统计:由于本题构造出来的字符串合法即可,所有最后的答案不是 dp[1][n],而是所有合法的dp[i][j] ,即Σdp[i][j] ( m≤j≤n )
CODE:
#include<bits/stdc++.h> using namespace std; #define ll long long #define db long double #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second #define popcount __builtin_popcount #define popcountll __builtin_popcountll const int N=3010; //const int M=; //const int inf=(int)1e9; //const ll INF=(ll)1e18; const ll MOD=998244353; int T,n; ll dp[N][N]; char s[N],t[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); // ios::sync_with_stdio(0); // cin.tie(0); scanf("%s",s+1);scanf("%s",t+1); int n=strlen(s+1),m=strlen(t+1); for(int i=1;i<=m;i++) dp[i][i]=2*(s[1]==t[i]); for(int i=m+1;i<=n;i++) dp[i][i]=2; for(int len=2;len<=n;len++) for(int i=1;i+len-1<=n;i++) { int j=i+len-1; // dp[i][j] if(i>m||s[len]==t[i]) dp[i][j]=(dp[i][j]+dp[i+1][j])%MOD; if(j>m||s[len]==t[j]) dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD; } ll ans=0; for(int i=m;i<=n;i++) ans=(ans+dp[1][i])%MOD; // for(int i=1;i<=n;i++) // for(int j=1;j<=n;j++) // printf("%d %d %d\n",i,j,dp[i][j]); printf("%lld\n",ans); return 0; }