地址:http://acm.hdu.edu.cn/showproblem.php?pid=4512
题意:中文。。
mark:最长升序公共子序列(LCIS)的一个小变形,最长公共子序列具体可以百度。
假设两个字符串为a,b,状态dp[i][j]代表a的前i个字符和b的前j个字符的最大匹配
当a[i] == b[j]时,dp[i][j] = max(dp[i-1][k])+1,k是[0 ... j-1]。
当a[i] != b[j]时,dp[i][j] = dp[i-1][j]。
dp[i-1][k]可以通过维护一个变量实现O(1)的算法,所以时间复杂度优化后是O(n^2),很显然计算数组第一维i的时候,只跟i-1有关,所以可以优化为一维数组。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <iostream> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <stack> using namespace std; typedef long long LL; int t,n; int a[210],b[210]; int dp[210]; int ans; int pd(int i, int j) { for(int k = i+1; k < n-j+1; k++) if(a[k] > a[i]) return 1; return 0; } int main() { int i,j,k; cin >> t; while(t--) { cin >> n; for(i = 1; i <= n; i++) { cin >> a[i]; b[n-i+1] = a[i]; } memset(dp, 0, sizeof(dp)); ans = 1; for(i = 1; i <= n; i++) for(j = 1, k = 0; j <= n; j++) { if(i >= n-j+1) break; if(a[i] > b[j]) k = max(k, dp[j]); if(a[i] == b[j]) { dp[j] = k+1; int flag = pd(i, j); ans = max(ans, 2*dp[j]+flag); } } cout << ans << endl; } return 0; }