Codeforces Round#635 1337E.Kaavi and Magic Spell(区间dp)

题目描述:

E. Kaavi and Magic Spell

time limit per test 2 seconds

memory limit per test 512 megabytes

Kaavi, the mysterious fortune teller, deeply believes that one’s fate is inevitable and unavoidable. Of course, she makes her living by predicting others’ future. While doing divination, Kaavi believes that magic spells can provide great power for her to see the future.

Kaavi has a string T of length m and all the strings with the prefix T are magic spells. Kaavi also has a string S of length n and an empty string A.

During the divination, Kaavi needs to perform a sequence of operations. There are two different operations:

Delete the first character of S and add it at the front of A.
Delete the first character of S and add it at the back of A.
Kaavi can perform no more than n operations. To finish the divination, she wants to know the number of different operation sequences to make A a magic spell (i.e. with the prefix T). As her assistant, can you help her? The answer might be huge, so Kaavi only needs to know the answer modulo 998244353.

Two operation sequences are considered different if they are different in length or there exists an i that their i-th operation is different.

A substring is a contiguous sequence of characters within a string. A prefix of a string S is a substring of S that occurs at the beginning of S.

Input
The first line contains a string S of length n (1≤n≤3000).

The second line contains a string T of length m (1≤m≤n).

Both strings contain only lowercase Latin letters.

Output
The output contains only one integer — the answer modulo 998244353.

Examples
input

abab
ba

output

12

input

defineintlonglong
signedmain

output

0

input

rotator
rotator

output

4

input

cacdcdbbbb
bdcaccdbbb

output

24

算法标签:区间dp

题目大意:给出两个字符串S和T,以及一个空串A,从左至右依次选择S中的每一个字符,并对其进行以下一个操作:

1.添加到A的首部

2.添加到A的尾部

求一共有多少种操作方式使得构成的字符串A的前缀为T(答案对998244353取模)。

样例1的示意图:
在这里插入图片描述

首先观察数据规模(n,m<=3000),刚好可以存一个二维数组,可以考虑区间dp。考虑任何一种符合要求的字符串A,以上图中的“baab”为例。
在这里插入图片描述
发现可以根据最后一个字符的添加方式(首部/尾部)来分成两类,也就为后续的状态转移提供了思路。

规定dp[i][j]:用s[1…i]表示一个合法的A[j…j+i-1]的方案数。 什么叫合法的A呢,意思就是A的前缀为T。

假设T一共有m位,那么对于A[1…m],A[k]需要与T[k]一一对应,即A[k]==T[k]。而m+1位以后,A[k]则可以为任意字符。

再根据最后一个字符的两种添加方式(首部/尾部),得出状态转移方程:

1. 添加在尾部:如果s[i]==t[j+i-1]或者j+i-1>m,dp[i][j]+=dp[i-1][j]

2. 添加在首部:如果s[i]==t[j]或者j>m,dp[i][j]+=dp[i-1][j+1]

起点状态设置d[0][k]=1,最后依次考虑A的长度m、m+1、…、n,累加dp[i][1]得到答案。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=3e3+5,mod=998244353;

char s[N],t[N];

ll dp[N][N];

int main()
{
    scanf("%s%s",s+1,t+1);
    int n=strlen(s+1),m=strlen(t+1);
    for (int j=1;j<=n+1;j++) dp[0][j]=1;
    for (int i=1;i<=n;i++)//s[1..i]  t[j..j+i-1]
    {
        for (int j=1;j<=n-i+1;j++)
        {
            if (s[i]==t[j+i-1]||j+i-1>m)
                dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
            if (s[i]==t[j]||j>m)
                dp[i][j]=(dp[i][j]+dp[i-1][j+1])%mod;
        }
    }
    ll ans=0;
    for (int i=m;i<=n;i++)
        ans=(ans+dp[i][1])%mod;
    printf("%lld",ans);
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值