自学内容网 自学内容网

最大公共子序列c++

概念

基本的概念

  • 子序列: 由原序列中若干个元素组成,元素可以不连续,但和原序列的顺序一致。
  • 最长公共子序列: 一个序列即是甲序列的子序列,也是乙序列的子序列,则该序列称为为甲和乙的公共子序列。长度最长的公共子序列,即最长公共子序列。
  • 两个序列的公共子序列不一定是唯一的。

递归

算法

  • lcs(s1,s2)表示:串s1和s2的最大公共子序列长度,并返回其值
  • 先比较两个串的首字符,如果相等,递归实现lcs(s1+1,s2+1)+1即可
  • 如果不相等,则返回lcs(s1,s2+1),lcs(s1+1,s2)中较大的。
    在这里插入图片描述
  • 由上图可以看出,最大公共子序列的值为3,但不唯一,abc,bca的长度都是3。

代码

#include<iostream>
using namespace std;
int lcs(const char* a,const char* b){
if(*a == 0 || *b==0) 
return 0;
if(*a==*b)
return lcs(a+1,b+1)+1;
return max(lcs(a,b+1),lcs(a+1,b));
} 
int main(){
cout<<lcs("axbcydz","xayybcxd")<<endl;
return 0;
}

优化

  • 递归的优点是思路简单,但是耗费资源,重复递归调用。
  • 如下图,草拟相同圈处是重复递归计算的地方,如果串长些,那么这种重计划量将非常繁巨,以致电脑无法计算。
    在这里插入图片描述
  • 所以需改进,改进的方法是,相同的串相互比较求最大公共子序列时,就将其存储起来,放入map,下次再遇到相同的2个串比较时,直调从map中取值。
  • 因为加入了参递,所以递归函数需要增参。
  • 递归函数f(m,s1,k1,s2,k2)
  • 参数说明。m是map记录着2个子串的最大公共子序列,s1、s2是子串,k1、k2是从子串的哪个下标开始比较。
  • 即只需以k1\k2的位置作为键,递归函数的返回值(最大公共子序列的长度)作为值,存入map中即可。

map基础

  • 头文件,#include
  • map存取键-值对,查找速度快。键需能比较,此应用中键为2个int,int。
  • stl中的pair可以保存<int,int>。定义为
#include <utility> // 包含 std::pair 的头文件
#include <iostream>
using namespace std;
int main() {
    // 直接初始化 std::pair
    pair<int, double> pair1(1, 3.14);
    // 使用 std::make_pair 函数初始化 std::pair
    pair<string, int> pair2 = make_pair("Kimi", 2024);
    // 访问 pair 的元素
    cout << "pair1: " << pair1.first << ", " << pair1.second << endl;
    cout << "pair2: " << pair2.first << ", " << pair2.second << endl;
    // 修改 pair 的元素
    pair1.first = 2;
    pair2.second = 2025;

    return 0;
}
  • map中统计键pair出现的次数
#include <iostream>
#include <map>
using namespace std;
int main() {
    map<pair<int, int>, string> map;
    // 插入键值对
    map[make_pair(1, 2)] = "12";
    map[make_pair(1, 2)] = "21"; // 注意:这实际上是更新了键(1, 2)的值
    map[make_pair(3, 4)] = "34";
    // 要查找的键
    pair<int, int> key_to_count(1, 2);
    // 使用count查找键
    size_t count = map.count(key_to_count);
    cout << "The key (" << key_to_count.first << ", " << key_to_count.second << ") appears " << count << " times." << endl;
    return 0;
}
  • map中查找pair对
#include <iostream>
#include <map>
#include <utility> // For std::pair
using namespace std;
int main() {
    // 创建一个map,键为pair<int, int>,值为string
    map<pair<int, int>, string> map;
    // 插入键值对
    map[make_pair(1, 2)] = "12";
    map[make_pair(3, 4)] = "34";
    // 要查找的键
    pair<int, int> key_to_find(1, 2);
    // 使用find查找键
    auto it = map.find(key_to_find);
    if (it != map.end()) {
        cout << "Found key: (" << it->first.first << ", " << it->first.second << ") with value: " << it->second << endl;
    } else {
        cout << "Key not found." << endl;
    }
    return 0;
}
  • map遍历
#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> myMap;
    // 插入一些键值对
    myMap[1] = "one";
    myMap[2] = "two";
    myMap[3] = "three";
    // 使用 begin() 获取指向第一个元素的迭代器
    auto it = myMap.begin();
    // 检查迭代器是否不是 end()(即检查 map 是否不为空)
    if (it != myMap.end()) {
        // 使用迭代器访问并打印第一个元素
        std::cout << "The first key-value is: " << it->first << " => " << it->second << std::endl;
    }
    // 使用范围基于的 for 循环遍历 map
    for (const auto& pair : myMap) {
        std::cout << pair.first << " => " << pair.second << '\n';
    }
    return 0;
}
  • 自定义pair对
#include <iostream>
#include <map>
using namespace std;
// 定义一个结构体作为键
struct IntPair {
    int first;
    int second;
    // 必须定义比较运算符,以便map可以比较键
    bool operator<(const IntPair& other) const {
        return first < other.first || (first == other.first && second < other.second);
    }
};
int main() {
    // 定义一个map,键为IntPair,值为string
    std::map<IntPair, std::string> map;
    // 插入键值对
    map[{1, 2}] = "12";
    map[{3, 4}] = "34";
    // 访问键值对
    for (const auto& kv : map) {
        cout << "Key: (" << kv.first.first << ", " << kv.first.second << ") Value: " << kv.second << endl;
    }

    return 0;
}

优化代码

#include<iostream>
#include<map>
using namespace std;
int f(map<pair<int,int>,int>& m,const char* s1,int k1,const char* s2,int k2){
if(s1[k1]==0 || s2[k2]==0)
return 0;
pair<int,int> p(k1,k2); //构建子串pair对 
if(m.count(p))//查找map中是否有相应的子串最大公共子序列值
return m[p];//如果存储了,则直接返回子序列长度,不必再递归计算 
//map中未记录,才计算最大公共子序列的长度 
if(s1[k1]==s2[k2]){ 
int t=f(m,s1,k1+1,s2,k2+1)+1;
m[make_pair(k1,k2)]=t;
return t;
}
int t1=f(m,s1,k1+1,s2,k2);
int t2=f(m,s1,k1,s2,k2+1);
int t=max(t1,t2);
m[make_pair(k1,k2)]=t;
return t;
}
int lcs(const char* s1,const char* s2){
//map<int,int>ma;
map<pair<int,int>,int> m;//定义一个map,键为pair<int,int>,值为int。 
return f(m,s1,0,s2,0);
} 
int main(){
cout<<lcs("axbcydz","xayybcxd")<<endl;
cout<<lcs("axbcydzaxbcydz","xayybcxdaaaaabbbxxccc")<<endl;
return 0;
}

原文地址:https://blog.csdn.net/qq_37755459/article/details/142983498

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!