线性dp
lis
最长的递增子序列
- 初始化值时应该是1(如果递增也最少是这个元素,最少是1)
- dp[i]表示到这个之前的最大递增的数
for(int i = 0;i < len; i++){
dp[i] = 1;
for(int j = 0;j < i; j++){
if(a[j] < a[i]) dp[i] = max(dp[i],dp[j]+1);
}
//筛出最大值
ans = max(ans,dp[i]);
}
lcs
最长的相同公共子序列
- 初始化值不用变,都是零。
- dp[i][j] 表示第一个串的第i个之前和第二个串的第j个之前匹配的最大值。
for(int i = 1;i <= a.size(); i++){
for(int j = 1;j <= b.size(); 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]);
}
}
回文串
bool is(int l ,int r){} //判断这个区间是否为回文串
for(int i = 1;i < str.length();i++){
//初始化
dp[i] = i+1;
for(int j = 1;j <= i;j++)
if(is(j,i)) dp[i] = min(dp[i],dp[j-1]+1);
}
题目大意:
给出一个字符串,看最少拆成多少回文子串。
//
// main.cpp
// 线性dp_切割出回文串
//
// Created by 陈冉飞 on 2019/9/11.
// Copyright © 2019 陈冉飞. All rights reserved.
//
#include <iostream>
using namespace std;
#define maxn 10010
char s[maxn];
int dp[maxn]; //dp[i][j]表示区间i到区间j的最小的回文串的长度
bool is_ok(int l,int r){
while (l <= r) {
if (s[l] == s[r]) {
l++;r--;
}else return false;
}
return true;
}
int main(int argc, const char * argv[]){
scanf("%s",s+1);
int len = strlen(s+1);
// //检验是否为回文串
// for (int i = 1; i <= len; i++)
// for (int j = 1; j <= i; j++)
// cout<<j<<" "<<i<<" "<<is_ok(j, i)<<endl;
//init
for (int i = 1; i <= len; i++) {
//初始化
dp[i] = i+1;
for (int j = 1; j <= i; j++)
if (is_ok(j, i)) dp[i] = min(dp[i],dp[j-1]+1);
}
cout<<dp[len]<<endl;
return 0;
}
codeforce 607B
题目大意:给出一个数组,然后看每次拿出一个回文子串,然后看最少多少次把整个数组拿完
//
// main.cpp
// 线性dp_逐次拿出回文串
//
// Created by 陈冉飞 on 2019/9/12.
// Copyright © 2019 陈冉飞. All rights reserved.
//
#include <iostream>
using namespace std;
#define maxn 505
int dp[maxn][maxn],n,a[maxn]; //dp[i][j] 为从i到j这个区间中最少的次数
#define INF 0x3f3f3f
#include <cstring>
#define cl(a,b) memset(a,b,sizeof(a))
int main(int argc, const char * argv[]) {
scanf("%d",&n);
//初始化
cl(dp, INF);
for (int i = 1; i <= n; i++) {scanf("%d",&a[i]);dp[i][i] = 1;}
//先遍历长度
for (int len = 1; len <= n; len++) {
for (int i = 1; i+len <= n; i++) {
int j = i+len;
if (a[i] == a[j]){
dp[i][j] = len;
//排除aa这种情况的特判
if (dp[i][j]!= 1) dp[i][j] = dp[i+1][j-1];
}
for (int k = i; k <= j; k++) dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
cout<<dp[1][n]<<endl;
return 0;
}