【LCS】POJ1458-Common Subsequence(模板)+LCS 的DP值算法解释

又到了本宝宝讲故事的时间辣!好吧并不是什么好故事。。。话说成天A题能找到老婆吗!没关系我老婆是电脑……诶。。。←这句话不是我说的


      还是看题吧,模板题不记录一下会很不爽,这是初级的LCS题,就是只需要算出最大公共子序列的元素个数就行了!

那么接下来说一下这道题需要用到的LCS知识点吧!

      LCS,就是最大公共子序列,给你两个字符串,其中相同的最长的两个字符串都含有的子序列就是我们要求的结果。注意这里面说的子序列是不要求连续的。

      举栗子说,有 abcfc 和 abfcab 两个字符串,那么他们的LCS就是 abfc ,这就告诉我们尽管abfc对于abcfc中间少了一个c,但它仍然是abcfc的子序列。

      要想求LCS,遍历不用想一定超时,怎么办?动态规划来解决!

      首先我们需要一个二维数组dp[na][nb],na是第一个字符串的字符数,n2是第二个字符串的字符数,哎呀空说不行,还要举例子!

      比如说现在有 abcfc 和 abfcab 两个字符串,要求最大公共子序列的元素个数,咋弄咧,由于说建立了一个二维的dp数组,我们将其用表格来呈现!


      咱们规定每个字符串下标从1开始,所以第二行和第二列都是0,表示跳过字符串数组第一个符号。

      但是这里会出现一个问题,就是字符串数组第一个元素如果是空着的话,会被自动填充为'\0',用strlen()函数读取字符串长度时,遇到的第一个'\0'就是0号元素,读取长度是0,咋弄呢?根据题意,在读取完字符串时再给两个字符串的0号元素一个题中明显没有的符号就行了。

      好,下面介绍表格内容:第一行是字符串a的每个元素,第一列是字符串b的每个元素,中间空着的地方用来存放当检查到当前格子时,最大公共子串所含有的元素个数。

      好神奇,原理是什么?

      首先要注意这种算法后面的数据是要根据前面推得的,而且要同时遍历两个字符串元素。

      我们知道每个格子记录的是最大公共子串所含有的元素个数,什么意思?就比方说图中第5行第5列来讲(下面出现的坐标都表示第几行第几列,比如string那一格坐标是(1,1)而不是(0,0)),这里面如果有数字,那么这里面的数字就代表根据字符串 abc 和 abf 这两个字符串所找到的最大公共子列的元素个数。

      我们设定i和j分别表示坐标,(i,j)表示第i行第j列的空格。

      这种算法是这样工作的:先设定第2行与第2列都是0,因为不管检查到哪里,字符串的每个元素都不跟a[0] or b[0]匹配,所以此时最大元素子串都是0。好,现在设定双重循环,针对这张图,外循环i初始是3,内循环j初始值是3,a[3]与b[3]都是a,好,匹配!这时候需要在上一个已经找到的最大公共子串数字基础上加一!阿列,这是找到的第一个?没事,那就当上一个最大公共子列元素个数是0就好啦,实际上上一个最大公共子列是dp[i-1][j-1]中所储存的数据,就是当前格子左上方那个格子所储存的数据。所以dp(3,3)就是dp(2,2)+1,就是1啦。下面来到dp(3,4),很明显a[3]与b[4]不匹配,呀,咋弄?废话,既然匹配失败了,当然最大公共子串元素个数不会增加了,那么当前格子数字应该填什么?当然是上一个最大dp值了~注意,此时最大的上一个dp值有两个情况,一个是dp[i-1][j]可能是最大的,也有可能是dp[i][j-1],就是上面那个格子的值或者是左边的那个,上面那个我们刚刚填过,有可能是最大的,左边那个因为长度检查到了b串当前元素的上一个元素,如果那个元素与a串匹配了,那么左边那个也有可能是最大的数,所以我们直接在这两个格子中选较大的值填入当前格子就OK了,这样一直循环到每个字符串的最后一个元素,那么dp最后一个元素就是我们要找的最大子串的值了(图中最大的值的坐标是(7,8))

这个表格填完以后是这样的:


好啦,格子填完了,答案也就出来了,想要详细理解的可以再看看介个视频:十分钟搞定LCS

下面上题!

【题目】

Common Subsequence
Time Limit: 1000MS Memory Limit: 10000K
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxx

Description

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..., xm > another sequence Z = < z1, z2, ..., zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, ..., ik > of indices of X such that for all j = 1,2,...,k, x ij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

Input

The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

Output

For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

Sample Input

abcfbc         abfcab
programming    contest 
abcd           mnp

Sample Output

4
2
0

【题意】

给你两个字符串,求最大公共子串的元素个数

      输入:两个字符串,中间用空格隔开,处理到EOF

      输出:最大公共子串元素个数,输出占一行

【思路】

      求解过程上面说过了,要注意如果想让字符串第一个元素下标是1,scanf的时候要取a[1]的地址,还有如果这样做的话别忘了设定下标为0的元素值不为‘\0’哦!还有这样的话计算字符串的长度的时候第0号元素会被计算在内,别忘了减一。

【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

char a[1005],b[1005];
int dp[1005][1005];

int main()
{
	while(scanf("%s%s",&a[1],&b[1])!=EOF)//这样取地址是为了设置第一个元素下标为 1
	{
		a[0]='!';
		b[0]='@';//别忘了设置第0个元素内容不是'\0'! 
		int na=strlen(a)-1;
		int nb=strlen(b)-1;//这样做会多算一个长度(第0号元素多被计算在内)所以要减一 
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=na;i++)//核心代码,填写表格 
		{
			for(int j=1;j<=nb;j++)
			{
				if(a[i]==b[j])
				dp[i][j]=dp[i-1][j-1]+1;
				else
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
			}
		}
		printf("%d\n",dp[na][nb]);
	}
}



      这篇博客我写了快两个小时了,手要废了。。。TAT 看我这么辛苦,你就点一下下面那个赞吧,没错就是下面那个!

      还有点击我头像下面的“+加关注”就可以关注我了,以后发表有趣的文章的时候会有提醒哦~嗯?你不要点一下吗,点一下不花钱的~真的!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值