HDU 1159 最长公共子序列

f(i,j)= {f(i-1,j-1)+1 (a[i]==b[j])

max(f(i-1,j),f(i,j-1)) (a[i]!=b[j]) 

由于f(i,j)只和f(i-1,j-1), f(i-1,j)和f(i,j-1)有关, 而在计算f(i,j)时, 只要选择一个合适的顺序, 就可以保证这三项都已经计算出来了, 这样就可以计算出f(i,j). 这样一直推到f(len(a),len(b))就得到所要求的解了.

#include<stdio.h>
#include<string.h>
int t[1000][1000];
int max(int x,int y)
{
	if(x>y)
		return x;
	else 
		return y;
}
int main()
{
	char a[1000],b[1000];
	int n,m,i,j;
//	freopen("1159.txt","r",stdin);
	memset(a,0,1000*sizeof(char));
	memset(b,0,1000*sizeof(char));
	while(scanf("%s%s%*c",a,b)!=EOF)
	{
		memset(t,0,sizeof(t));
		n=strlen(a);
		m=strlen(b);
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
			{
				if(a[i-1]==b[j-1])
					t[i][j]=t[i-1][j-1]+1;
				else
					t[i][j]=max(t[i-1][j],t[i][j-1]);
			}
		}
		printf("%d\n",t[n][m]);
	}
}

修改后同时可以输出最长公共子序列

#include<stdio.h>
#include<string.h>
int t[1000][1000],c[1000][1000];
int main()
{
	char a[1000],b[1000],e[1000];
	int n,m,i,j,k,len;
	freopen("1159.txt","r",stdin);
	memset(a,0,1000*sizeof(char));
	memset(b,0,1000*sizeof(char));
	while(scanf("%s%s%*c",a,b)!=EOF)
	{
		memset(e,0,sizeof(e));
		memset(t,0,sizeof(t));
		n=strlen(a);
		m=strlen(b);
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
			{
				if(a[i-1]==b[j-1])
				{
					t[i][j]=t[i-1][j-1]+1;
					c[i][j]=1;//对角线方向
				}	
				else if(t[i-1][j]>t[i][j-1])
				{
					t[i][j]=t[i-1][j];
					c[i][j]=2;//上面来的
				}
				else
				{
					t[i][j]=t[i][j-1];
					c[i][j]=3;//左边来的
				}
			}
		}
		printf("%d\n",t[n][m]);
		i=n;
		j=m;
		len=t[n][m];
		k=len;
		while(k)
		{
			if(c[i][j]==1)
			{
				i--;
				j--;
				e[k-1]=a[i];
				k--;
			}
			else if(c[i][j]==2)
			{
				i--;
			}
			else if(c[i][j]==3)
			{
				j--;
			}
		}
		for(i=0;i<len;i++)
		{
			printf("%c ",e[i]);
			if(i<len-1)
				putchar(' ');
			else if(i==len-1)
				printf("\n");
		}

	}
	return 0;
}



你可能感兴趣的:(HDU 1159 最长公共子序列)