(Relax DP1.5)POJ 1458 Common Subsequence(使用dp来求解最长公共子串)

本文详细阐述了如何通过动态规划算法解决寻找两个字符串中最长公共子字符串的问题,包括状态选择、状态转移方程以及核心代码实现。通过实例演示,帮助读者理解并掌握此算法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 问题描述:给出两个字符串,求它们最长的公共子字符串。

              形如:abcfbc  和 abfcab,其中adb,adcb,abfc都是它们的公共子串,而abcb,abfc是它们的最长公共子串。 

¡
¡    状态选择
         dp[i][j]代表第一个字符串前i个字符组成的字符串与第二个字符串前j个字符组成的字符串的最长公共子串的长度.
    状态转移方程
           如果str1[i-1]==str2[j-1],dp[i][j]=dp[i-1] [j-1]+1;       
           否则dp[i][j]=max{ dp[i-1][j],dp[i] [j-1]}.
    初始条件:
           dp[0][j]=0,0<=j<=len2;
           dp[i][0]=0,0<=i<=len1.
    核心代码
            for(i=0;i<=len1;i++) dp[i][0]=0;            //初始化条件
            for(j=0;j<=len2;j++) dp[0][j]=0;           //初始化条件
            for(i=1;i<=len1;i++){                  //求第一个串的第i个字符与第二个串中的前j个字符的最长公共串
               for(j=1;j<=len2;j++) 
               {  
                 if(str1[i-1]==str2[j-1])          //如果相等就表示该处的值比前一个点处的值多1
                        dp[i][j]=dp[i-1][j-1]+1;  
                  else                            //否则是能去同行前一列和前一行同列值中的较大者
                        dp[i][j]=dp[i-1][j]>dp[i][j-1]?dp[i-1][j]:dp[i][j-1]; 
               }
             }
    输出
          经过以上的处理,dp[i][j]中已经保存了许多值,如今我们只需要里面的一个最大值即可。
           max=0;
           for(i=1;i<=lena;i++){              //寻最大数 
                for(j=1;j<=lenb;j++){
                   if(dp[i][j]>max)max=dp[i][j];
                }
            }
           则,max极为所求。

/*
 * POJ_1458.cpp
 *
 *  Created on: 2013年12月17日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 1005;
int dp[maxn][maxn];


int main() {
	char str1[maxn], str2[maxn];
	while (scanf("%s %s", str1, str2) != EOF) {

		memset(dp, 0, sizeof(dp));

		int len1 = strlen(str1);
		int len2 = strlen(str2);

		int i, j;


		for (i = 1; i <= len1; ++i) {
			for (j = 1; j <= len2; ++j) {
				if(str1[i-1] == str2[j-1]){//***这里是需要注意的,因为第i个字符的下标为i-1
					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[len1][len2]);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅气的东哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值