最长公共子序列

题目 : https://www.luogu.com.cn/problem/P1439

最长公共子序列(简化版)

字串的长度 n<=1000
时间复杂度高,大概是O(n2
使用二维数组进行状态转移,有一个固定的公式。
(dp[i][j]=egin{cases} max(dp[i-1][j], do[i][j-1]) + 1 quad s[i] =t[j]\\ max(dp[i-1][j], do[i][j-1]) quad s[i] !=t[j]end{cases})

#include <cstdio>  
using namespace std;  
const int MAXN =1e3+5;  
int a[MAXN],b[MAXN];  
int dp[MAXN][MAXN];  
int max(int a,int b){  
    return a>b?a:b;  
}  
int main(){  
    int N;  
  scanf("%d",&N);  
 for(int i=1;i<=N;i++)  
        scanf("%d",&a[i]);  
 for(int i=1;i<=N;i++)  
        scanf("%d",&b[i]);  
 for(int i=1;i<=N;i++){  
        for(int j=1;j<=N;j++){  
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);  
 if(a[i]==b[j]){  
                dp[i][j]++;  
  }  
        }  
    }  
//    for(int i=1;i<=N;i++){  
//        for(int j=1;j<=N;j++)  
//            printf("%d ",dp[i][j]);  
//        printf("
");  
//    }  
  printf("%d
",dp[N][N]);  
 return 0;  
}

最长公共子序列(进阶版)

n<=100000
题解 : 将一个序列离散化,离散化只有变成1 2 3 4 5 ......
则要求最长公共子序列就会转化为求最长上升子序列,按照进阶版的二分进行查找添加,更新值就会成为结果。注意题目中的1-n的排列。

#include <map>  
#include <cstdio>  
#include <vector>  
#include <iostream>  
using namespace std;  
const int MAXN = 1e5+5;  
int a[MAXN],b[MAXN];  
int main(){  
    int N;  
	scanf("%d",&N);  
    map<int,int>m;  
    m.clear();  
    for(int i=0;i<N;i++){  
        scanf("%d",&a[i]);  
        m[a[i]]=i+1;  
	}  
    for(int i=0;i<N;i++){  
        scanf("%d",&b[i]);  
		b[i]=m[b[i]];  
    }  
    vector<int>v;  
    v.push_back(b[0]);  
    for(int i=1;i<N;i++){  
        int l=0,r=v.size();  
        if(b[i]>v[v.size()-1]) 
            v.push_back(b[i]);  
        else{  
            while(l<r){  
                int mid=(l+r)/2;  
				if(b[i]>v[mid])l=mid+1;  
				else r=mid;  
	        }  
            v[l]=b[i];  
		}  
    }  
    printf("%d
",v.size());  
	return 0;  
}
原文地址:https://www.cnblogs.com/Vagrant-ac/p/12244229.html