Kaavi and Magic Spell
题解
由于要求的是两个字符串经过前后放置后相等的情况,于是我们很容易发现,在前缀已经相等的情况下,将剩余的放在后面是一定成立的。于是乎,我们可以不用统计完一直到放完的情况,统计前缀相同后的情况即可。
我们先将目标字符串补全为一个后面为任意字符的长度与原字符串相等的串,这样方便摆放时的匹配。
由于它放时是前后皆可,于是我们发现放置好的个数一定对应了目标串中一个长度为的区间。我们便自然而然地想到了区间dp。
令为已放置的个字符匹配目标串中区间的串,转移方程也很好想
。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 3005
typedef long long LL;
const LL INF=0x7f7f7f7f7f7f;
const LL mo=998244353;
typedef pair<int,int> pii;
typedef tuple<LL,LL,LL,LL> tp;
#define gc() getchar()
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=gc();while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}x*=f;
}
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
char astr[MAXN],bstr[MAXN];
LL lena,lenb,dp[MAXN][MAXN],ans;
signed main(){scanf("%s\n%s",astr,bstr);lena=(LL)strlen(astr);lenb=(LL)strlen(bstr);for(int i=0;i<lenb;i++)dp[i][i]=2*(astr[0]==bstr[i]);for(int i=lenb;i<lena;i++)dp[i][i]=2;for(int i=1;i<lena;i++)for(int l=0;l<lena-i;l++){int r=l+i;if(l>=lenb||bstr[l]==astr[i])(dp[l][r]+=dp[l+1][r])%=mo;if(r>=lenb||bstr[r]==astr[i])(dp[l][r]+=dp[l][r-1])%=mo;//printf("%d %d:%lld\n",l,r,dp[l][r]);}for(int i=lenb-1;i<lena;i++)(ans+=dp[0][i])%=mo;printf("%lld\n",ans);return 0;
}