1. 程式人生 > 實用技巧 >Shortest Common Non-Subsequence

Shortest Common Non-Subsequence

題目連結: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; }