根据题目数据范围可以知道算法的时间复杂度应当是O(nlogn)。具体思路应当是将最长公共子序列问题转到最长上升子序列(LIS问题有时间复杂度O(nlogn))。具体可以参考这篇文章:最长上升子序列 例如:
求上面两个序列的最长公共子序列,可以将上面的的序列 1 6 5 4 3 2 转换成 1 2 3 4 5 6。即有1->1 , 6->2 , 5->3 , 4->4 , 3->5 , 2->6。的对应方法。最后转换成下面这个样子。 求两个序列的公共子序列就是求下面序列的最长上升子序列。下面的代码中translate()函数就是转换的方法。
代码如下:
#include<iostream>//根据题目范围知道这道题要用nlogn 的算法,用n^2的算***超时,将LCS的问题转化为LIS的问题是解决本题的关键。
#include<algorithm>
using namespace std;
const int maxn = 100005;
int n;
int a[maxn], b[maxn],v[maxn],id[maxn];// id[x] : x被编成了几号
//int dp[maxn];
inline void input()//输入函数
{
cin >> n;
for (int i = 1;i <= n;i++)
cin >> a[i];
for (int i = 1;i <= n;i++)
cin >> b[i];
}
inline int query()
{
v[1] = a[1];
int ans = 1;
for (int i = 2;i <= n;i++)
{
if (a[i] > v[ans])
v[++ans] = a[i];
else//为了使上升子序列最长,应当使序列中的值之间相差尽可能的小。 *p=a[i];的目的就是舍弃之前的值,用新的a[i]来顶替它。
{
int* p = lower_bound(v + 1, v + 1 + ans, a[i]);
*p = a[i];
}
}
return ans;
/*for(int i=1;i<=n;i++)//朴素做法,时间复杂度为n^2
for (int j = n;j >=1;j--)
{
if (a[i] == b[j])
dp[j] = max(dp[j - 1] + 1, dp[j]);
else
dp[j] = max(dp[j], dp[j - 1]);
}
return dp[n];*/
}
inline void translate()
{
for (int i = 1;i <= n;i++)//将数字进行转化的精髓
id[b[i]] = i;
for (int i = 1;i <= n;i++)
a[i] = id[a[i]];
/*for (int i = 1;i <= n;i++)
b[i]=i;*/
}
int main()
{
ios::sync_with_stdio(false);
input();
translate();
/*for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++)
cout<<b[i]<<" ";
cout<<endl;*/
int k = query();
cout << k << endl;
}
以上是关于这道模板题的讲解。下面来对LCS问题进行分析。复杂度为O(n^2)。 对于长度为n的序列A和长度为m的序列B。 具体可以这样思考: dp[i][j]是长度为i的序列A和长度为j的序列B的最长公共子序列。 1.A[i]==B[j],则有dp[i][j]=dp[i-1][j-1]+1; 2.A[i]!=B[j], 则有dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int A[105],B[105];
int dp[105][105];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>A[i];
for(int i=1;i<=m;i++)
cin>>B[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(A[i]==B[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
cout<<dp[n][m]<<endl;
}
参考资料: https://www.zhihu.com/question/23995189 https://www.luogu.com.cn/blog/pks-LOVING/junior-dynamic-programming-dong-tai-gui-hua-chu-bu-ge-zhong-zi-xu-lie