1337E - Kaavi and Magic Spell[ d p dp dp]
time limit per test | memory limit per test | input | output |
---|---|---|---|
2 seconds | 256 megabytes | standard input | standard 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(1≤n≤3000).
The second line contains a string T T T of length m ( 1 ≤ m ≤ n ) m (1≤m≤n) m(1≤m≤n).
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]
-
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+1→r] 的左边一个位置 -
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][r−1]
至于初始化有两种写法
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][r−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;
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;
}