第一次尝试
看到题目,感觉只会回溯,于是写出如下代码:
#include<bits/stdc++.h>
using namespace std;
int n_color,len, n;
vector<int> pattern, stripe;
int maxLen = -1;
void match(int idx, int j, int l) {
if(j == n) {
if(l > maxLen)
maxLen = l;
return;
}
if(pattern[idx] == stripe[j]) {
++l;
// 继续匹配pattern[idx]位置的颜色
match(idx, j + 1, l);
// 否则匹配idx + 1了(如果还有的话)
if(idx + 1 < len)
match(idx + 1, j + 1, l);
} else {
// 不匹配,则只能跳过
match(idx, j + 1, l);
}
// 不可能匹配idx要跳过j,因为order固定了。这样只会更短
// match(idx,)
}
int main() {
cin >> n_color >> len;
pattern.resize(len);
for(int i = 0; i < len; ++i) {
cin >> pattern[i];
}
cin >> n;
stripe.resize(n);
for(int i = 0; i < n; ++i) {
cin >> stripe[i];
}
match(0,0,0);
cout << maxLen << endl;
}
提交发现思路应该是正确的,但是上述没有缓存结果,导致超时了。
第二次尝试
仔细看一下数据量,是两个串的匹配问题。(动态规划的)时间复杂度为
O
(
N
K
)
<
1
0
5
O(NK)<10^5
O(NK)<105,肯定不会超时的,因此接下来写成DP形式。
根据上面的思路,只要逆向枚举,就可以避免反复计算一些中间值。
那么状态转移方程直接按照match方法里的写就好了,即:
d
p
[
i
]
[
j
]
=
{
max
(
d
p
[
i
]
[
j
+
1
]
,
d
p
[
i
+
1
]
[
j
+
1
]
)
+
1
i
f
p
a
t
t
e
r
n
[
i
]
=
=
s
t
r
i
p
e
[
j
]
d
p
[
i
+
1
]
[
j
+
1
]
e
l
s
e
dp[i][j]=\left\{ \begin{align*} &\max(dp[i][j+1],dp[i+1][j+1])+1 & & {if \quad pattern[i] == stripe[j] } \\ &dp[i+1][j+1] & &{else} \end{align*} \right.
dp[i][j]={max(dp[i][j+1],dp[i+1][j+1])+1dp[i+1][j+1]ifpattern[i]==stripe[j]else
其中
i
=
0
,
1
,
.
.
.
,
l
e
n
−
1
;
j
=
0
,
1
,
2
,
.
.
.
,
n
−
1
i=0,1,..., len - 1; j= 0,1,2,...,n - 1
i=0,1,...,len−1;j=0,1,2,...,n−1
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示
p
a
t
t
e
r
n
[
0..
i
]
pattern[0..i]
pattern[0..i]与
s
t
r
i
p
e
[
0..
j
]
stripe[0..j]
stripe[0..j]按照题意匹配所能得到的最大长度。
于是得到如下代码:
#include<bits/stdc++.h>
using namespace std;
int n_color, len, n;
vector<int> pattern, stripe;
int main() {
cin >> n_color >> len;
pattern.resize(len);
for(int i = 0; i < len; ++i) {
cin >> pattern[i];
}
cin >> n;
stripe.resize(n);
for(int i = 0; i < n; ++i) {
cin >> stripe[i];
}
vector<vector<int>> dp(len + 1, vector<int>(n + 1));
dp[len][n] = 0; //
for(int i = len - 1; i >= 0; --i) {
for(int j = n - 1; j >= 0; --j) {
if(pattern[i] == stripe[j]) {
dp[i][j] = max(dp[i][j + 1], dp[i + 1][j + 1]) + 1;
} else {
dp[i][j] = dp[i][j + 1];
}
}
}
cout << dp[0][0] << endl;
}