[CF1336C] Kaavi and Magic Spell

5 篇文章 0 订阅

题目

戳这儿上洛谷

题意

题意很简单,看洛谷就好了。

思路

拿到这题真是毫无头绪。
瞥了一眼题解代码——怎么这么短?难道这题并不难?然而再想了会儿,搞了几个错误的思路。最后还是得细看题解。不得不说,这状态设计确实巧妙,确实不知道是怎么想到的。那么直接讲题解的做法。

考虑 区间 d p \tt dp dp,令 d p [ l ] [ r ] dp[l][r] dp[l][r] 为用 S S S 的前 r − l + 1 r-l+1 rl+1 得到 t [ l − r ] t[l-r] t[lr] 的方案数。

对于 t i = = s 1 t_i==s_1 ti==s1,或者 i > l e n t i>lent i>lent d p [ i ] [ i ] = 2 dp[i][i]=2 dp[i][i]=2

而:
我们考虑固定一个 l l l,枚举 L e n Len Len,那么 r r r 就为 l + L e n − 1 l+Len-1 l+Len1

  • 如果 s L e n = = t l s_{Len}==t_l sLen==tl 或者 l > l e n t l >lent l>lent,那么 d p [ l ] [ r ] dp[l][r] dp[l][r] 可从 d p [ l + 1 ] [ r ] dp[l+1][r] dp[l+1][r] 转移来
  • 如果 s L e n = = t r s_{Len}==t_r sLen==tr 或者 r > l e n t r > lent r>lent,那么 d p [ l ] [ r ] dp[l][r] dp[l][r] 可从 d p [ l ] [ r − 1 ] dp[l][r-1] dp[l][r1] 转移来

Update

在蒋永神的引领下,我似乎知道了该题状态设计的大体思路。

我们考虑对于 S S S 串中的其他元素,并不能确定它在 T T T 中的位置。然而,只有 S S S 中的最后一个元素,我们知道它一定是 T T T 中的第一个或最后一个元素,那么这是我们就可以将其对应 T T T 匹配,并将 S S S 中前一位元素进行下一步转移。那么这就相当于是一个左右端点收拢的一个匹配问题,自然可以用 区间 d p \tt dp dp解决,而状态的设计也就迎刃而解了。

Code

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define MAXN 3005
#define Int register int
#define Mod 998244353
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
inline LL Abs(LL x)
{
	if (x > 0)
		return x;
	return - x;
}
inline LL Min(LL x,LL y)
{
	return x < y ? x : y;
}
inline LL Max(LL x,LL y)
{
	return x > y ? x : y;
}
inline void read(LL &x)
{
	x = 0;
	LL f = 1;
	char s = getchar();
	while (s < '0' || s > '9')
	{
		if (s == '-')
			f = -1;
		s = getchar();
	}
	while (s >= '0' && s <= '9')
	{
		x = (x << 3) + (x << 1) + (s ^ 48);
		s = getchar();
	}
	x *= f;
}
char S[MAXN], T[MAXN];
LL dp[MAXN][MAXN];
int main()
{
	scanf("%s", S + 1);
	scanf("%s", T + 1);
	LL Lens = strlen(S + 1);
	LL Lent = strlen(T + 1);
	for (Int i = 1; i <= Lens; ++ i)
		if (S[1] == T[i] || i > Lent)
			dp[i][i] = 2;
	for (Int Len = 1; Len <= Lens; ++ Len)
		for (Int l = 1; l + Len - 1 <= Lens; ++ l)
		{
			LL r = l + Len - 1;
			if (r > Lent || S[Len] == T[r])
				dp[l][r] += dp[l][r - 1], dp[l][r] %= Mod;
			if (l > Lent || S[Len] == T[l])
				dp[l][r] += dp[l + 1][r], dp[l][r] %= Mod;
		}
	LL Ans = 0;
	for (Int i = Lent; i <= Lens; ++ i)
		Ans += dp[1][i], Ans %= Mod;
	printf("%lld", Ans);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值