题目链接:https://ac.nowcoder.com/acm/contest/7831/D
题意:给出两个 01 串 a 和 b,求最短的 01 串 t ,使得 t 不是 a 和 b 的子序列,若有多个答案则输出字典序最小的。
思路:先用自动序列预处理下,然后再dfs记录即可。
a 串 [x,lena]区间 和 b 串[y,lenb]区间的最优解可能性分两种,
0 + [ a[x][0] , lena ]区间和[ b[x][0] , lenb ]区间的最优解;
1 + [a[x][1] , lena]区间和[b[x][1] , lenb]区间的最优解;
#include<bits/stdc++.h> using namespace std; typedef long long ll; char a[4005],b[4005]; int lena,lenb; int dp[4005][4005],f[4005][4005]; int nexa[4005][2],nexb[4005][2]; vector<int> ans; int dfs(int x,int y) { if(x==lena+1&&y==lenb+1) return 0; if(dp[x][y]) return dp[x][y]; int tmp0=dfs(nexa[x][0],nexb[y][0]); int tmp1=dfs(nexa[x][1],nexb[y][1]); if(tmp0<=tmp1) f[x][y]=0; else f[x][y]=1; dp[x][y]=min(tmp0,tmp1)+1; return dp[x][y]; } void fun(int x,int y) { if(x==lena+1&&y==lenb+1) return; int tmp=f[x][y]; ans.push_back(tmp); fun(nexa[x][tmp],nexb[y][tmp]); } int main() { scanf("%s",a+1); scanf("%s",b+1); lena=strlen(a+1); lenb=strlen(b+1); nexa[lena+1][0]=nexa[lena+1][1]=lena+1; nexb[lenb+1][0]=nexb[lenb+1][1]=lenb+1; for(int i=lena;i>=0;i--) { nexa[i][0]=nexa[i+1][0]; nexa[i][1]=nexa[i+1][1]; if(a[i+1]=='0') nexa[i][0]=i+1; else nexa[i][1]=i+1; } for(int i=lenb;i>=0;i--) { nexb[i][0]=nexb[i+1][0]; nexb[i][1]=nexb[i+1][1]; if(b[i+1]=='0') nexb[i][0]=i+1; else nexb[i][1]=i+1; } dfs(0,0); fun(0,0); for(int i=0;i<ans.size();i++) cout<<ans[i]; cout<<endl; }