最长公共子序列
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
string a,b;
int dp[1000][1000];
void cal_lcs()//计算最长公共子序列长度
{
for(int i=1;i<=a.length();i++)
{
for(int j=1;j<=b.length();j++)
{
if(a[i-1]==b[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
}
void get_lcs()//得到最长公共子序列
{
int i=a.length(),j=b.length();
char res[1000];
int cnt=0;
while(i!=0&&j!=0)
{
//如果a[i-1]==b[i-1] 那么dp[i][j]就来源于dp[i-1][j-1]
if(a[i-1]==b[j-1])//如果相等,那他肯定是公共子序列的一员
{
res[cnt++]=a[i-1];
i--;j--;
}
//否则 dp[i][j]来源于dp[i-1][j]或者dp[i][j-1]中最大的
else if(dp[i-1][j]<dp[i][j-1])
j--;
else
i--;
}
for(int i=cnt-1;i>=0;i--)
cout << res[i];
}
int main()
{
cin >> a >> b;
cal_lcs();
get_lcs();
cout << dp[a.length()][b.length()] << endl;
}
最长上升子序列
#include<iostream>
#include<cstring>
using namespace std;
int d[10000],a[10000];
int lis(int a[],int n){
memset(d,0,sizeof d);
int len = 1;
d[1] = a[0];
for(int i = 1;i < n;i++){
if(a[i] > d[len]) //严格递增
d[++len] = a[i];
else{
//lower_bound查找d数组中1-len中第一个大于等于a[i]的位置 并用a[i]替代他
d[lower_bound(d,d+len,a[i])-d]=a[i];
}
}
for(int i = 1;i <= len;i++)
cout << d[i]<<" ";
return len;
}
int main()
{
int n;
cin >> n;
for(int i=0;i<n;i++)
cin >> a[i];
lis(a,n);
}
最长不下降子序列
#include<iostream>
#include<cstring>
using namespace std;
int d[10000],a[10000];
int lis(int a[],int n){
memset(d,0,sizeof d);
int len = 1;
d[1] = a[0];
for(int i = 1;i < n;i++){
if(a[i] >= d[len]) //把上面的代码改为大于等于
d[++len] = a[i];
else{
//upper_bound查找d数组中1-len中第一个大于a[i]的位置 并用a[i]替代他
d[upper_bound(d,d+len,a[i])-d]=a[i];
}
}
for(int i = 1;i <= len;i++)
cout << d[i]<<" ";
return len;
}
int main()
{
int n;
cin >> n;
for(int i=0;i<n;i++)
cin >> a[i];
lis(a,n);
}
和最大子序列
他的最大和子序列可能存在于0~mid或mid+1~n-1或横跨mid左边有一点右边有一点
#include<iostream>
using namespace std;
int n;
int a[100001];
int getMax(int left,int right)
{
if(left==right)
return a[left];
int mid=(left+right)/2;
int lsum=getMax(left,mid);//左半部分的和最大子序列
int rsum=getMax(mid+1,right);//右半部分的和最大子序列
int t=0,t1=0,t2=0;
for(int i=mid;i>=left;i--)
{
t+=a[i];
if(t>t1)
t1=t;
}
t=0;
for(int i=mid+1;i<=right;i++)
{
t+=a[i];
if(t>t2)
t2=t;
}
int msum=t1+t2;//横跨左右的和最大子序列
return max(lsum,max(msum,rsum));
}
int main()
{
cin >> n;
for(int i=0;i<n;i++)
cin >> a[i];
cout << getMax(0,n-1);
}