[Codeforces Round #635 (div2)]1337E - Kaavi and Magic Spell[dp]

1337E - Kaavi and Magic Spell[ d p dp dp]

time limit per testmemory limit per testinputoutput
2 seconds256 megabytesstandard inputstandard output

Description:

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 T T of length m and all the strings with the prefix T T T are magic spells. Kaavi also has a string S S S of length n n n and an empty string A A A.

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

  Delete the first character of S S S and add it at the front of A A A.
  Delete the first character of S S S and add it at the back of A A A.

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

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

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

Input

TThe first line contains a string S S S of length n ( 1 ≤ n ≤ 3000 ) n (1≤n≤3000) n(1n3000).

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

Both strings contain only lowercase Latin letters.

Output

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


One Example input

abab
ba

One Example output

12

Two Example input

defineintlonglong
signedmain

Two Example output

0

Three Example input

rotator
rotator

Three Example output

4

Four Example input

cacdcdbbbb
bdcaccdbbb

Four Example output

24

Hit

The first test:
在这里插入图片描述
The red ones are the magic spells. In the first operation, Kaavi can either add the first character “a” at the front or the back of A A A, although the results are the same, they are considered as different operations. So the answer is 6 × 2 = 12 6×2=12 6×2=12.


分析:
题意:
A A A 串一开始为空串
每次可以取 S S S 串的第一个字母,放在 A A A 串的首位置或者末位置
问在放字母的过程中,总共会有多少个串的前缀有 T T T

做法:
万物皆可 d p dp dp只是我不会系列
参考博客 CodeForces - 1337E Kaavi and Magic Spell(dp)

d p [ l ] [ r ] dp[l][r] dp[l][r] 表示串 t t t [ l , r ] [l,r] [l,r] 区间内的可以匹配的种类数
对于 s [ i ] s[i] s[i]

  1. s [ i ] = = t [ l ] s[i] == t[l] s[i]==t[l],那么 s [ i ] s[i] s[i] 可以放在 t [ l ] t[l] t[l] 的位置,种类数则为 d p [ l ] [ r ] = d p [ l ] [ r ] + d p [ l + 1 ] [ r ] dp[l][r] = dp[l][r] + dp[l+1][r] dp[l][r]=dp[l][r]+dp[l+1][r]
    d p [ l + 1 ] [ r ] dp[l+1][r] dp[l+1][r] 就是表示 s [ i ] s[i] s[i] 放在原本可以匹配好的 t [ l + 1 → r ] t[l+1\rightarrow r] t[l+1r] 的左边一个位置
  2. s [ i ] = = t [ r ] s[i] == t[r] s[i]==t[r] 同理,表示 s [ i ] s[i] s[i] 可以放在 t [ r ] t[r] t[r] 的位置
    则种类数为 d p [ l ] [ r ] = d p [ l ] [ r ] + d p [ l ] [ r − 1 ] dp[l][r] = dp[l][r] + dp[l][r-1] dp[l][r]=dp[l][r]+dp[l][r1]

至于初始化有两种写法

for(int i = 1; i <= n; ++i)	dp[i][i-1] = 1;

s [ i ] = = t [ r ] s[i] == t[r] s[i]==t[r] 的时候, d p [ r ] [ r ] = d p [ r ] [ r ] + d p [ r ] [ r − 1 ] dp[r][r] = dp[r][r] + dp[r][r-1] dp[r][r]=dp[r][r]+dp[r][r1]
就相当于表示这个位置可以选择填进去匹配

或者 如果这个位置可以匹配,我有两种方式,放前面或者放后面(我也不晓得,我自己理解是这样的)

for(int i = 1; i <= m; ++i)
    if(s[1] == t[i])    dp[i][i] = 2;
for(int i = m + 1; i <= n; ++i)
    dp[i][i] = 2;

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e3 + 5;
const int mod = 998244353;

char s[maxn], t[maxn];
ll dp[maxn][maxn]; // t l->r 匹配方案数

int main() {
    scanf("%s%s", s + 1, t + 1);
    memset(dp, 0, sizeof(dp));
    int n = strlen(s + 1), m = strlen(t + 1);
    for(int i = 1; i <= m; ++i)
        if(s[1] == t[i])    dp[i][i] = 2;
    for(int i = m + 1; i <= n; ++i)
        dp[i][i] = 2;
    // for(int i = 1; i <= n + 1; ++i)  dp[i][i-1] = 1;
    for(int i = 1; i <= n; ++i) {
        for(int l = 1, r = l + i - 1; r <= n; ++l, ++r) {
            if(l > m || s[i] == t[l]) // 前插
                dp[l][r] = (dp[l][r] + dp[l + 1][r]) % mod;
            if(r > m || s[i] == t[r]) // 后插
                dp[l][r] = (dp[l][r] + dp[l][r - 1]) % mod;
        }
    }
    ll ans = 0;
    for(int i = m; i <= n; ++i)
        ans = (ans + dp[1][i]) % mod;
    printf("%lld\n", ans);
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值