nyoj17_又做最大递增子序列

时间:2023-03-08 23:57:02
nyoj17_又做最大递增子序列

单调递增最长子序列

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述
求一个字符串的最长递增子序列的长度 如:dabdbf最长递增子序列就是abdf,长度为4
输入
第一行一个整数0<n<20,表示有n个字符串要处理 随后的n行,每行有一个字符串,该字符串的长度不会超过10000
输出
输出字符串的最长递增子序列的长度
样例输入
3
aaa
ababc
abklmncdefg
样例输出
1
3
7
来源
经典题目
上传者
iphxer
先用之前学过的方法做过一遍,这个的时间复杂度是O(n²),从挑战程序设计竞赛上看到竟然还有O(nlogn)的方法!!
#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; char a[];
int b[]={}; int main()
{
int n;
scanf("%d",&n);
for(int i=;i<n;i++){
int ans=;
scanf("%s",a);
int len=strlen(a);
fill(b,b+len,);
for(int j=;j<len;j++){
int maxx=;
for(int k=;k<j;k++){
if(a[k]<a[j]){
maxx=max(b[k],maxx);
}
}
b[j]=maxx+;
ans=max(b[j],ans);
}
printf("%d\n",ans);
}
return ;
}

这是O(nlogn)的方法,利用lower_bound()函数。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; //solve()需要三个全局
char a[];
int b[]={};
const int INF=;
int len; void solve(){
fill(b,b+len,INF);
for(int i=;i<len;i++){
*lower_bound(b,b+len,a[i])=a[i];//这里在比较的时候是以a[i]的ascii值比较的
}
printf("%d\n",lower_bound(b,b+len,INF)-b);
} int main()
{
int n;
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%s",a);
len=strlen(a);
solve();
}
return ;
}