首页 > 其他分享 >最长公共子序列(局限性)(LCS)问题

最长公共子序列(局限性)(LCS)问题

时间:2024-04-21 22:34:11浏览次数:19  
标签:LCS int cvt 局限性 low 数组 LIS 序列

先来个朴素dp算法!见代码注释

点击查看代码
//原理:dp
//时间复杂度:o(n^2),过不了本题
#include <bits/stdc++.h>
using namespace std;
int f[1001][1001];//dp数组,f[i][j]为处理了a的前i位,b的前j位得到的最长公共子序列
int a[1001];
int b[1001];
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);//加快输入输出
    int n;
    cin>>n;
    for (int i = 1;i<=n;i++) cin>>a[i];
    for (int i = 1;i<=n;i++) cin>>b[i];
    for (int i = 1;i<=n;i++)//dp,处理f[i][j]
    {
        for (int j = 1;j<=n;j++)
        {
            if(a[i] == b[j]) f[i][j] = f[i-1][j-1] + 1;//如果当前a[i] == b[j],则可以长度加1
            else f[i][j] = max(f[i-1][j],f[i][j-1]);//否则转移最大值(观察下标,之前的已经计算过了)
        }
    }
    cout<<f[n][n]<<"\n";//输出答案
    return 0;
}


显然上述解法仅适用于1e4范围 而有没有更快的解法? 当然,对于特殊序列:两个序列元素互异且相同,便可以转化为LIS问题 原理解释及证明: map记录下b[]的每个元素的位置,然后利用a[]得到一个在b中对应元素的位置序列cvt[],为什么可以转化为LIS问题呢? 不妨以a[5] = [3 2 1 4 5],b[5] = [1 2 3 4 5],得到的cvt数组为cvt[5] = [3,2,1,4,5],当然你a,b数组可以反着来操作,无所谓 不妨取cvt中对应一个位置为假设LCS的起点,因为LCS是按顺序来的,那么比起点小的位置均无效,那么除去该起点及所有比起点小的位置,剩下的 情况转换成了一个子问题重复,故动态规划解.而起点又又多个选择,故变成找最长的上升子序列了.故LCS->LIS合理!

下面就是代码了,更多细节见注释.

点击查看代码
#include <bits/stdc++.h>
using namespace std;
map<int,int> b;//用哈希表不一定有红黑树快,对于可能卡哈希的,而红黑树一定过的,优先用红黑树(acmer的严谨,我这里不管)
int a[100001];//a数组
int cvt[100001];//转换得到的cvt数组
int low[100001];//长度为i的LIS的最后一个数的最小值
int m = 0;//LIS最大长度,初始化为0
int Find(int x)//二分查找
{
    int ans = 0;//初始化答案
    int l = 0;
    int r = m;
    while(l<=r)//二分
    {
        int mid = (l+r)>>1;
        if(low[mid] >= x)//一定要等于,否则就不满足LIS性质了(即单调上升,可能会导致单调不减)
        {
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);//加快输入输出
    memset(low,-127,sizeof(low));//low数组初始化为负无穷,防止新的数比low[1]还小的情况的Hack!(自己感悟)
    int n,x;
    cin>>n;//输入数量
    for (int i = 1;i<=n;i++) cin>>a[i];//输入a数组
    for (int i = 1;i<=n;i++)//处理b数组
    {
        cin>>x;
        b[x] = i;//记下位置
    }
    for (int i = 1;i<=n;i++)//生成cvt数组
    {
        cvt[i] = b[a[i]];
    }
    for (int i = 1;i<=n;i++)//LIS模板
    {
        if(cvt[i]>low[m]) low[++m] = cvt[i];//直接接上
        else
        {
            int p = Find(cvt[i]);
            low[p] = cvt[i];//更新位置最小值
        }
    }
    cout<<m<<"\n";//输出答案,即LIS长度
    return 0;
}

标签:LCS,int,cvt,局限性,low,数组,LIS,序列
From: https://www.cnblogs.com/cuijunjie18/p/18149644

相关文章

  • 序列化反序列化
    【一】序列化常见字段​ 序列化类中有很多多字段,如CharFieldIntegerField,他们会跟models里面的字段一一对应,除了这些,序列化类还多出了两个字段ListField和DictField,非常重要字段字段构造方式BooleanFieldBooleanField()NullBooleanFieldNullBooleanField()......
  • 新手大白话 [SWPUCTF 2021 新生赛]babyunser phar反序列化
    进入赛题网站第一眼以为是文件上传,尝试没效果,看题目标签为phar反序列化,这类也就是文件包含php伪协议的一种,实质上就是上传phar文件,利用网页给予的文件读取页面利用phar伪协议进行读取来触发一句话木马,好现在开始做题。(一点也不新生)利用查看文件来收集信息,查看read.php点击查看......
  • Java安全基础之Java序列化与反序列化
    目录ObjectInputStream和ObjectOutputStreamjava.io.Serializable自定义序列化和反序列化Java的序列化(Serialization)是指将对象转换为字节序列的过程,而反序列化(Deserialization)则是将字节序列转换回对象的过程。序列化和反序列化通常用于在网络上传输对象或者将对象持久化到......
  • 01、Java 安全-反序列化基础
    Java反序列化基础1.ObjectOutputStream与ObjectInputStream类1.1.ObjectOutputStream类java.io.ObjectOutputStream类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。序列化操作一个对象要想序列化,必须满足两个条件:该类必须实现java.io.Serializable接口,......
  • 掌握时间序列特征工程:常用特征总结与 Feature-engine 的应用
    时间序列数据的特征工程是一种技术,用于从时间序列数据中提取信息或构造特征,这些特征可用于提高机器学习模型的性能。以下是一些常见的时间序列特征工程技术:滚动统计量:计算时间窗口内的统计量,如平均值、中位数、标准偏差、最小值和最大值。这些统计量可以捕捉到时间序列在不同时......
  • JZ33 二叉排序树的后序遍历序列
    classSolution{public://判断该数组是不是某二叉搜索树的后序遍历的结果。//如果是则返回true,否则返回false//注意传入参数是一个int类型的vector容器boolVerifySquenceOfBST(vector<int>sequence){if(sequence.empty()) //二叉树......
  • 31天【代码随想录算法训练营34期】第八章 贪心算法 part01(● 理论基础 ● 455.分发
    贪心算法就是先选局部最优,再推全局最优没有套路将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解●455.分发饼干classSolution:deffindContentChildren(self,g:List[int],s:List[int])->int:g.s......
  • leedcode-判断子序列
    自己写的,有点麻烦classSolution:defisSubsequence(self,s:str,t:str)->bool:#第一步先验证s是t的无序子序列#使用字典记录t中每个字符的出现次数mydict=dict()foriint:ifnotmydict.get(i):......
  • json反序列化 JsonConvert.DeserializeObject 报错 One or more errors occurred. (U
    接口返回的字符串肉眼看起来正常,也是标准json,反序列化时候报错,字符串添加了UTF8-BOM头(windows记事本默认编码),可以通过以下代码移除标头//模拟json字符串对象varjsonStr="{}";byte[]buffer=Encoding.UTF8.GetBytes(jsonStr);varsResult=Encoding.UTF8.GetString......
  • 记录一次CTF解题PHP反序列
    攻防世界的一个php反序列化题unserialize3PHP反序列化序列化通俗来讲就是将对象转化为可以传输的字符串,反序列化就是把那串可以传输的字符串再变回对象。<?phpclasschybate{var$test='123456';}$cless1=newchybate;//序列化$cless1_ser=serialize($cle......