题面
这题一打眼
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示方案数啊!
但是仔细想想不对 这个
d
p
dp
dp式体现不出当前字符和前一个串的关系 (
d
p
dp
dp式:n你少加一维还怪我了?)
所以我们要再加一维
0
/
1
0/1
0/1表示当前字符是接在上一个子串
/
/
/当前字符是一个新的子串的开端
0
/
1
0/1
0/1开两个数组更直观一点:
我们用
a
n
s
[
i
]
[
j
]
[
k
]
ans[i][j][k]
ans[i][j][k]表示到
A
A
A字符串第
i
i
i个字符
B
B
B字符串第
j
j
j个字符 当前子串数为
k
k
k的答案数
s
u
m
[
i
]
[
j
]
[
k
]
sum[i][j][k]
sum[i][j][k]表示当前在
A
A
A字符串第
i
i
i个字符
B
B
B字符串第
j
j
j个字符 当前子串数为
k
k
k时的方案数
然后就是关系式了 怎么搞呢
首先考虑当前的
a
n
s
ans
ans 要么用
A
[
i
]
A[i]
A[i]要么不用
所以
a
n
s
[
i
]
[
j
]
[
l
]
=
a
n
s
[
i
−
1
]
[
j
]
[
l
]
+
s
u
m
[
i
]
[
j
]
[
l
]
ans[i][j][l]=ans[i-1][j][l]+sum[i][j][l]
ans[i][j][l]=ans[i−1][j][l]+sum[i][j][l]
显而易见 当
A
[
i
]
≠
B
[
i
]
A[i]\neq B[i]
A[i]=B[i]时
s
u
m
sum
sum的值就是
0
0
0
经过思考可知当
A
[
i
]
=
B
[
i
]
A[i]=B[i]
A[i]=B[i]时 此时要么接在上个子串上 要么开一个新的子串
所以
s
u
m
[
i
]
[
j
]
[
l
]
=
s
u
m
[
i
−
1
]
[
j
−
1
]
[
l
]
+
a
n
s
[
i
−
1
]
[
j
−
1
]
[
l
−
1
]
sum[i][j][l]=sum[i-1][j-1][l]+ans[i-1][j-1][l-1]
sum[i][j][l]=sum[i−1][j−1][l]+ans[i−1][j−1][l−1]
哈哈 做完了?想得美
d
p
[
1000
]
[
200
]
[
200
]
[
2
]
?
?
dp[1000][200][200][2]??
dp[1000][200][200][2]??显然是炸的 所以我们要优化空间
注意到第一维貌似没什么卵用 所以直接滚掉
空间复杂度
O
(
4
m
k
)
O(4mk)
O(4mk)时间复杂度
O
(
n
m
k
)
O(nmk)
O(nmk) 没啥大问题
上代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,m,k,now,ans[2][202][202],sum[2][202][202];
char a[1010],b[202];
int main(){
cin>>n>>m>>k;
scanf("%s%s",a+1,b+1);
ans[0][0][0]=ans[1][0][0]=now=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int l=1;l<=k;l++){
if(a[i]==b[j])sum[now][j][l]=(sum[now^1][j-1][l]+ans[now^1][j-1][l-1])%mod;
else sum[now][j][l]=0;
ans[now][j][l]=(ans[now^1][j][l]+sum[now][j][l])%mod;
}
}
now^=1;
}
printf("%d\n",ans[now^1][m][k]);
}
代码倒还不长哈?
P
.
S
.
P.S.
P.S.由于上个月逃间操被抓
+
+
+月考太差
+
+
+太菜导致现在没脸半脱产 (估计申请时班主任教练员两关都过不去所以不能跟高二一起考试…没办法只能多做做
N
O
I
P
NOIP
NOIP原题看看知识点了…委屈屈
.
j
p
g
.jpg
.jpg