dp[ i+1 ][ j+1 ]=dp[ i ][ j ]+1 ( s[i]==t[j] )
dp[ i+1 ][ j+1 ]=max(dp[ i ][ j+1 ] , dp[ i+1 ][ j ] ) (其他)
自己理解下,不懂的去百度;
看了好多大神的博客,总结了以下代码:
#include
using namespace std;
const int MAX_N=2005;
string s,t;
int dp[MAX_N][MAX_N];
int pre[MAX_N][MAX_N]; //标记路径
vector ans; //保存路径
void output(int x,int y){
if(x==0||y==0) return ; //超出边界。dp数组是从[1,n],[1~n]来定义的
else if(pre[x][y]==1){ //pre=1,状态是从左上方转移过来的,往左上方找
output(x-1,y-1); //递归地往回找
ans.push_back(s[x-1]); //保存路径,这里我保存了数值,也可以保存下标,x-1。
}
else if(pre[x][y]==2){ //pre=2,状态是从正上方转移过来的,往正上方找
output(x-1,y);
}
else if(pre[x][y]==3){ //pre=3,状态是从左边转移过来的,往左边找
output(x,y-1);
}
}
int main(){
cin>>s>>t;
int n=s.length(),m=t.length(); //以dp[i+1][j+1]为讨论对象
for(int i=0;idp[i+1][j]){ //正上方的大于左边的
dp[i+1][j+1]=dp[i][j+1]; //从正上方转移过来
pre[i+1][j+1]=2;
}
else{
dp[i+1][j+1]=dp[i+1][j]; //左边的大于正上方的
pre[i+1][j+1]=3; //左边转移过来
}
}
}
cout<
参考来自大神:王小二的博客
pre数组和output函数是用来保存路径的,不需要的话直接去掉就行。
dp[ i ] :以a[ i ] 为结尾的最长上升子序列的长度:
以a[i]为结尾的上升子序列有两类:
1:只包含a[ i ]的子序列,元素个数为1 ,(一开始就对左右元素的dp值初始化为1);
2:在满足j < i 并且 a[ j ] < a[ i ] 的以a[ j ]结尾,追加上a[ i ]得到的子序.
(1)O(n^2)复杂度解决方案:
#include
using namespace std;
const int MAX_N=2005;
int a[MAX_N];
int dp[MAX_N];
int pre[MAX_N]; //标记路径,记录前驱
int max_pos = 0; //最大位置
vector ans; //保存路径
void DFS(int pos){
if(pre[pos]!=-1) {
DFS(pre[pos]);
ans.push_back(a[pos]);
}
else{
ans.push_back(a[pos]);
return;
}
}
int main()
{
int n,i,j;
cin>>n;
for(i=0;i>a[i];
}
int res = 0; //最长上升子序列的长度
memset(pre,-1,sizeof(pre));
for(i=0;ia[j] && dp[i]=res){
res=dp[i]; max_pos=i;
pre[i]=j;
}
}
}
}
cout<
(2)O(nlogn)复杂度解决方案:
dp[ i ] :长度为i+1的上升子序列中末尾元素的最小值(不存在即为INF)
这个dp数组的更新非常有意思,自己可以下去模拟一下,但是要注意,dp数组只能保存最长上升子序列的长度,而不能保存正确的子序列。
比如 1 3 5 2 :dp数组最后保存的会是1 2 5 ,显然,这不是正确的顺序。
那么怎么保存路径呢?
传送门 (LIS路径还原)
#include
using namespace std;
const int MAX_N=2005;
const int INF=0x3f3f3f3f;
int a[MAX_N];
int dp[MAX_N];
int pre[MAX_N]; //标记路径,记录前驱
int pos[MAX_N];
vector ans; //保存路径
void output(int pos){
if(pre[pos]!=-1){
output(pre[pos]);
}
ans.push_back(pos+1);
}
int main(){
int n;
while(cin>>n&&n){
ans.clear();
for(int i=0;i>a[i];
}
fill(dp,dp+n,INF);
pos[0]=-1;
int i,now;
for(i=0;i