程序设计2

问题描述:字符串匹配,按照如下方法求出两个字符串的最大匹配位数.

输入:

MARRUPYG
AMTRROPC

输出:

appx(MARRUPYG,AMTRROPC) = 1/2

其中,appx 函数计算公式2个字符串最大匹配字符数*2/(字符串1长度+字符串2长度)

解题思路:

寻找最长公共子序列(Longest Common Subsequence, LCS),子序列不要求字符连续,而子串要求字符连续。

算法思路(最长公共子序列):

  1. 使用动态规划方法。创建一个二维数组 dp,其中 dpi 表示字符串1的前i个字符和字符串2的前j个字符的最长公共子序列的长度。

  2. 初始化:dp0 = dpi = 0,因为空字符串与任何字符串的LCS长度为0。

  3. 状态转移:

    • 如果字符串1的第i个字符等于字符串2的第j个字符,则 dpi = dpi-1 + 1

    • 否则,dpi = max(dpi-1, dpi)

  4. 填充完dp数组后,dpm就是最长公共子序列的长度。

  5. 要得到实际的LCS,我们需要从dp数组的右下角开始回溯。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
​
using namespace std;
​
class Solution {
public:
    string longestCommonSubsequence(const string& str1, const string& str2) {
        int m = str1.length();
        int n = str2.length();
        
        // 创建 dp 数组
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        
        // 填充 dp 数组
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (str1[i-1] == str2[j-1]) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                } else {
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        
        // 回溯找出 LCS
        string lcs;
        int i = m, j = n;
        while (i > 0 && j > 0) {
            if (str1[i-1] == str2[j-1]) {
                lcs = str1[i-1] + lcs;
                i--; j--;
            } else if (dp[i-1][j] > dp[i][j-1]) {
                i--;
            } else {
                j--;
            }
        }
        
        return lcs;
    }
};
​
int main() {
    Solution solution;
    
    string str1 = "MARRUPYG";
    string str2 = "AMTRROPC";
    
    string result = solution.longestCommonSubsequence(str1, str2);
    
    cout << "appx("+str1+","+str2+") = " << double(result.length()*2)/(str1.length()+str2.length()) << endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值