最长公共子序列
前置知识
子序列:一个字符串 'abc' ,它的子序列有 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc'
全排列,一个大小为 (N) 的数组,任意一个元素 (a_i) 满足 (1 ≤ a_i ≤ N),并且每个元素互不相同。
思路
-
对于一个全排列的,可以考虑先把它进行处理一下,处理的方法,就是对它进行一个
离散化使其变成一个 (1,2,3,...,N-1,N) 的排列,那么另一个序列就会发生改变。
-
之后对求解的问题就会变成求一个最长上升子序列的问题。
-
上升子序列存在一个状态转化的问题,使用 vector 存一个数组,
当 (a_i>) vector 中的最后一个元素的时候,在 vector 添加这个元素,
小于的时候,对 vector 对应的那个位置进行更新,那个位置就是对应的前一项小于 (a_i) ,
对应的后一项大于 (a_i)更新那个位置值的原因是因为,在此之前的 (a_i) 不会在对它进行使用,
而对它进行更新的话,可以让 vector 中存的元素尽量的小,更加方便后续元素的进入,
并且不会影响最长公共序列的长度的值。
实际上这是通过递推的思路进行解决,考虑前一个状态,并且对前一个状态不产生影响。
代码
这个是洛谷最长公共子序列的板子题
#include <map>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int N,x;
map<int,int>m;
cin>>N;
for(int i=0;i<N;++i){
cin>>x;m[x]=i+1;
}
vector<int>v;
for(int i=0;i<N;++i){
cin>>x;x=m[x];
if(v.size()==0||x>v[v.size()-1])v.push_back(x);
else{
int pos=lower_bound(v.begin(),v.end(),x)-v.begin();
v[pos]=x;
}
}
cout<<v.size()<<endl;
return 0;
}