Kaavi and Magic Spell

Kaavi and Magic Spell

题解

由于要求的是两个字符串经过前后放置后相等的情况,于是我们很容易发现,在前缀已经相等的情况下,将剩余的放在后面是一定成立的。于是乎,我们可以不用统计完一直到放完的情况,统计前缀相同后的情况即可。

我们先将目标字符串补全为一个后面为任意字符的长度与原字符串相等的串,这样方便摆放时的匹配。

由于它放时是前后皆可,于是我们发现放置好的k个数一定对应了目标串中一个长度为k的区间。我们便自然而然地想到了区间dp。

f_{l,r}为已放置的r-l+1个字符匹配目标串中区间[l,r]的串,转移方程也很好想

f_{l,r}=[b_{l}==a_{i}]dp_{l+1,r}+[b_{r}==a_{i}]dp_{l,r-1}

源码

#include
using namespace std;
#define MAXN 3005
typedef long long LL;
const LL INF=0x7f7f7f7f7f7f;
const LL mo=998244353;
typedef pair pii;
typedef tuple tp;
#define gc() getchar()
template
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
_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||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

谢谢!!!

你可能感兴趣的:(#,区间dp)