D. Shortest Common Non-Subsequence----(ICPC 2018 ASIA YOKOHAMA REGIONAL)

题意:给出两个 01 串 a 和 b,求最短的 01 串 t ,使得 t 不是 a 和 b 的子序列,若有多个答案则输出字典序最小的。

 

 

分析:分析一下,a 串 [x,lena]区间 和 b 串[y,lenb]区间的最优解可能性分两种

1)0 + [ nxta[x][0] , lena ]区间和[ nxtb[x][0] , lenb ]区间的最优解;

2)  1 + [ nxta[x][1] , lena ]区间和[ nxtb[x][1] , lenb ]区间的最优解;

其中 nxtk[i][j] 表示 k 串在第 i 个位置,下一个 j 的位置。

预处理 nxt 数组然后DP搜索一下就好了。

 

 

代码:

#include
#include
#include
#include
#include 
using namespace std;

const int N = 4000+10;

char a[N];
char b[N];
int nxta[N][2];
int nxtb[N][2];
int dp[N][N];
int f[N][N];
int lena,lenb;

vectorans;

int dfs(int x,int y)
{
	if(x==lena+1&&y==lenb+1) return 0;
	if(dp[x][y]) return dp[x][y];
	
	int tmp1=dfs(nxta[x][0],nxtb[y][0]);
    int tmp2=dfs(nxta[x][1],nxtb[y][1]);
   
    //根据题目要求,选择长度较小的为答案 
    if(tmp1<=tmp2) f[x][y]=0;
    else f[x][y]=1;
    
    return dp[x][y]=min(tmp1,tmp2)+1;
}

void getans(int x,int y)
{
	if(x==lena+1&&y==lenb+1) return;
	int tmp=f[x][y];
	ans.push_back(tmp);
	getans(nxta[x][tmp],nxtb[y][tmp]);
}

int main()
{
	scanf("%s%s",a+1,b+1);
	lena=strlen(a+1);
	lenb=strlen(b+1);
	
	nxta[lena+1][0]=nxta[lena+1][1]=lena+1;
	nxtb[lenb+1][0]=nxtb[lenb+1][1]=lenb+1;
	for(int i=lena;i>=0;i--)
	{
		nxta[i][0]=nxta[i+1][0];
	    nxta[i][1]=nxta[i+1][1];
	    if(a[i+1]=='0') nxta[i][0]=i+1;
	    else nxta[i][1]=i+1; 
	}
	
	for(int i=lenb;i>=0;i--)
	{
		nxtb[i][0]=nxtb[i+1][0];
	    nxtb[i][1]=nxtb[i+1][1];
	    if(b[i+1]=='0') nxtb[i][0]=i+1;
	    else nxtb[i][1]=i+1; 
	}
	
	dfs(0,0);
	getans(0,0);
	for(int i=0;i

 

你可能感兴趣的:(ICPC,2018,ASIA,YOKOHAMA,REGION)