概念
基本的概念
- 子序列: 由原序列中若干个元素组成,元素可以不连续,但和原序列的顺序一致。
- 最长公共子序列: 一个序列即是甲序列的子序列,也是乙序列的子序列,则该序列称为为甲和乙的公共子序列。长度最长的公共子序列,即最长公共子序列。
- 两个序列的公共子序列不一定是唯一的。
递归
算法
- 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>
#include <iostream>
using namespace std;
int main() {pair<int, double> pair1(1, 3.14);pair<string, int> pair2 = make_pair("Kimi", 2024);cout << "pair1: " << pair1.first << ", " << pair1.second << endl;cout << "pair2: " << pair2.first << ", " << pair2.second << endl;pair1.first = 2;pair2.second = 2025;return 0;
}
#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"; map[make_pair(3, 4)] = "34";pair<int, int> key_to_count(1, 2);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;
}
#include <iostream>
#include <map>
#include <utility>
using namespace std;
int main() {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);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;
}
#include <iostream>
#include <map>int main() {std::map<int, std::string> myMap;myMap[1] = "one";myMap[2] = "two";myMap[3] = "three";auto it = myMap.begin();if (it != myMap.end()) {std::cout << "The first key-value is: " << it->first << " => " << it->second << std::endl;}for (const auto& pair : myMap) {std::cout << pair.first << " => " << pair.second << '\n';}return 0;
}
#include <iostream>
#include <map>
using namespace std;
struct IntPair {int first;int second;bool operator<(const IntPair& other) const {return first < other.first || (first == other.first && second < other.second);}
};
int main() {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); if(m.count(p))return m[p];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<pair<int,int>,int> m;return f(m,s1,0,s2,0);
}
int main(){cout<<lcs("axbcydz","xayybcxd")<<endl;cout<<lcs("axbcydzaxbcydz","xayybcxdaaaaabbbxxccc")<<endl;return 0;
}