传送门
一个很显然的DP,考试的时候写wa了
O
(
n
2
)
O(n^2)
O(n2)DP
考虑当前
d
p
i
,
j
dp_{i,j}
dpi,j可以由什么转移过来
枚举当前填
c
=
′
0
′
/
′
1
′
c='0'/'1'
c=′0′/′1′
可以从
d
p
第
一
个
串
从
i
开
始
第
一
个
c
的
位
置
,
第
二
个
串
从
j
开
始
第
一
个
c
的
位
置
+
1
dp_{第一个串从i开始第一个c的位置,第二个串从j开始第一个c的位置}+1
dp第一个串从i开始第一个c的位置,第二个串从j开始第一个c的位置+1转移
输出的时候优先输出0就行了
Code:
#include <bits/stdc++.h>
#define maxn 4010
using namespace std;
char s1[maxn], s2[maxn];
int n, m, dp[maxn][maxn], nxt1[maxn], nxt2[maxn];
void dfs(int i, int j){
if (i > n && j > m) return;
if (dp[i][j]) return;
dp[i][j] = 1e9;
for (char c = '0'; c <= '1'; ++c){
int nxti = max(i, c == s1[i] ? i + 1 : nxt1[i] + 1),
nxtj = max(j, c == s2[j] ? j + 1 : nxt2[j] + 1);
if (nxti != i || nxtj != j) dfs(nxti, nxtj);
dp[i][j] = min(dp[i][j], dp[nxti][nxtj] + 1);
}
}
void print(int i, int j){
if (i > n && j > m) return;
for (char c = '0'; c <= '1'; ++c){
int nxti = max(i, c == s1[i] ? i + 1 : nxt1[i] + 1),
nxtj = max(j, c == s2[j] ? j + 1 : nxt2[j] + 1);
if (dp[i][j] == dp[nxti][nxtj] + 1){
putchar(c); print(nxti, nxtj); return;
}
}
}
int main(){
scanf("%s%s", s1 + 1, s2 + 1);
n = strlen(s1 + 1), m = strlen(s2 + 1);
s1[++n] = s2[++m] = '0';
nxt1[n] = n + 1, nxt2[m] = m + 1;
for (int i = n - 1; i; --i) nxt1[i] = s1[i] == s1[i + 1] ? nxt1[i + 1] : i + 1;
for (int i = m - 1; i; --i) nxt2[i] = s2[i] == s2[i + 1] ? nxt2[i + 1] : i + 1;
dfs(1, 1);
print(1, 1);
return 0;
}