1. 最长递增子序列
求长度
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
int LIS(int *d, int n) {
vector<int> g(n, 0);
int k = 0;
for(int i = 0; i < n; i++) {
int pos = lower_bound(g.begin(), g.begin()+k, d[i]) - g.begin();
if(pos == k) k++;
g[pos] = d[i];
}
for(int i = 0; i < k; i++) cout<<g[i]<<" ";
cout<<endl;
return k;
}
int main() {
int n;
while(cin>>n) {
int *d = new int[n];
for(int i = 0; i < n; i++) cin>>d[i];
cout<<LIS(d, n)<<endl;
delete[] d;
}
}
求长度与一条最短的序列,这种方法得到的一定是当前字典序最小的方案
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
int LIS(int *d, int n) {
vector<int> g(n, 0);
vector<int> p(n, 0);
int pre[n];
for(int i = 0; i < n; i++) pre[i] = i;
int k = 0;
for(int i = 0; i < n; i++) {
int pos = lower_bound(g.begin(), g.begin()+k, d[i]) - g.begin();
if(pos == k) k++;
g[pos] = d[i];
p[pos] = i;
if(pos) pre[i] = p[pos-1];
}
int t = p[k-1];
int j = k - 1;
vector<int> ans(k);
while(j >= 0) {
ans[j--] = d[t];
t = pre[t];
}
for(int i = 0; i < k; i++) cout<<ans[i]<<" ";
cout<<endl;
return k;
}
int main() {
int n;
while(cin>>n) {
int *d = new int[n];
for(int i = 0; i < n; i++) cin>>d[i];
cout<<LIS(d, n)<<endl;
delete[] d;
}
}
2. 最长非递减子序列(包含重复元素)
将上述函数的
lower_bound 修改为 upper_bound就可以了
这两个函数包含在头文件#include <algorithm>
3. 最长递增子串(求长度以及输出对应路径)
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
int LIS(int *d, int n) {
int max_len = 1;
int max_i = 0;
int cur_len = 1;
for(int i = 1; i < n; i++) {
if(d[i] > d[i-1]) cur_len++;
else cur_len = 1;
if(cur_len > max_len) {
max_len = cur_len;
max_i = i;
}
}
for(int i = max_i + 1 - max_len; i <= max_i; i++) cout<<d[i]<<" ";
cout<<endl;
cout<<"max_len = "<<max_len<<endl;
return max_len;
}
int main() {
int n;
while(cin>>n) {
int *d = new int[n];
for(int i = 0; i < n; i++) cin>>d[i];
cout<<LIS(d, n)<<endl;
delete[] d;
}
}