P8256字符串 题解
考虑\(DP\):
记状态 \(f_{i,j,st,en}\) 表示现在枚举到第 \(i\) 个字符,匹配了 \(j\) 个字符,要在前面删 \(st\) 个字符,在后面删 \(en\) 个字符的方案数
不难发现 \(f_{n+1,m,0,0}=1\)
状态转移有
当 \(s_i='-'\) 时,
有 \(f_{i,j,st,en}=f_{i+1,j,st-1,en}+f_{i+1,j,st,en-1}\)
当 \(s_i=0/1\) 时,
有 \(f_{i,j,st,en}=f_{i+1,j,st,en+1}\)
若 \(en=0\) 且 \(j=0\) 有 \(f_{i,0,st,0}+=f_{i+1,0,st+1,0}\)
若 \(j!=m\) 且 \(s_i=t_{j+1}\) 且 \(en=0\) 有 \(f_{i,j,st,0}+=f_{i+1,j+1,st,0}\)
考虑优化:
因为可以通过 \(i,j,st\) 推断出 \(en\) 所以 \(en\) 可以不要,只记三个状态 \(f_{i,j,st}\)
注意:当想思路清晰一些时,用记忆化搜索会比 \(DP\) 更好
上代码:
#include<bits/stdc++.h>
using namespace std;
const int N=405;
const int mod=1e9+7;
int T,n,m,len;
char s[N],t[N];
int f[N][N][N];
int dfs(int wz,int gs,int st,int en)
{
	if(wz>n) return gs==m&&!st&&!en;
	if(f[wz][gs][st]!=-1) return f[wz][gs][st];
	long long res=0;
	if(s[wz]=='-')
	{
		if(st) res=(res+dfs(wz+1,gs,st-1,en))%mod;
		if(en) res=(res+dfs(wz+1,gs,st,en-1))%mod;
	}
	else
	{
		res=dfs(wz+1,gs,st,en+1)%mod;
		if(!gs&&!en) res=(res+dfs(wz+1,0,st+1,0))%mod;
		if(gs!=m&&s[wz]==t[gs+1]&&!en) res=(res+dfs(wz+1,gs+1,st,0))%mod;
	}
	return f[wz][gs][st]=res%mod;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		memset(f,-1,sizeof f);
		scanf("%d %d %s %s",&n,&m,s+1,t+1);
		len=0;
		printf("%d\n",dfs(1,0,0,0));
	}
	return 0;
}
后记:真唐吧,两小时想不出这道题
                    
                
                
            
        
浙公网安备 33010602011771号