zoukankan      html  css  js  c++  java
  • P1439 【模板】最长公共子序列(LCS)

    先来看一看普通的最长公共子序列

    给定字符串A和B,求他们的最长公共子序列

    DP做法:

    设f[i][j]表示A[1~i]和B[1~j]的最长公共子序列的长度

    那么f[i][j]=max(f[i-1][j],f[i][j-1])

    在上面的基础上,如果A[i]=B[j],则f[i][j]=max(f[i][j],f[i-1][j-1]+1)

    代码:

     for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          {
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            if(a1[i]==a2[j])
            dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
          }

    复杂度为O(mn)


    那么这道题由于1e5的数据,不论是时间还是空间都会爆炸,就需要考虑另一种做法

    我们来观察这个题的特征,发现A和B都是1~n的全排列,也就是说A和B中元素是一样的,考虑充分利用这个特征。

     

    ——by pks大佬

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    int n,len;
    int atlas[100005],a[100005],f[100005];
    
    int main()
    {
        n=read();
        for(int i=1,x;i<=n;i++) 
        {
            x=read();
            atlas[x]=i;//每个数在序列1出现的位置 
        }
        for(int i=1,x,now;i<=n;i++) 
        {
            x=read();
            now=atlas[x];//在a序列找出x的位置 
            if(now>f[len])//如果位置在上一个的后面 
            {
                f[++len]=now;
            }
            else
            {
                int j=lower_bound(f+1,f+1+len,now)-f;//在f中找到第一个大于等于now的位置 
                f[j]=now;//更新 
            }
        }
        cout<<len;
     } 
  • 相关阅读:
    哲学的初步认识7
    随机法解决TSP问题
    哲学的初步认识6
    dfs+dp思想的结合------hdu1078
    动态规划3-------poj1050
    动态规划2-----hdu1069
    动态规划1-----------poj1080
    js中Math.round、parseInt、Math.floor和Math.ceil小数取整小结【转】
    美术馆
    无刷新评论
  • 原文地址:https://www.cnblogs.com/lcezych/p/11126816.html
Copyright © 2011-2022 走看看