單調遞增最長子序列
- 描述
- 求一個字符串的最長遞增子序列的長度
如:dabdbf最長遞增子序列就是abdf,長度爲4- 輸入
- 第一行一個整數0<n<20,表示有n個字符串要處理
隨後的n行,每行有一個字符串,該字符串的長度不會超過10000 - 輸出
- 輸出字符串的最長遞增子序列的長度
- 樣例輸入
-
3 aaa ababc abklmncdefg
- 樣例輸出
-
1 3 7
- 來源
- 經典題目
解析:LIS的裸題,
代碼:
1.O( n^2 )
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x7fffffff
const int maxn=10005;
int dp[maxn];
char a[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",a);
int l1=strlen(a);
int ans=0;
for(int i=0;i<l1;i++)
{
dp[i]=1; //只包含ai的子序列
for(int j=0;j<i;j++)
{
if(a[j]<a[i]) //在滿足j<i並且aj<ai的以aj爲結尾的上升子列末尾,追加上ai後得到的子序列
dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return 0;
}
O( nlogn )
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x7fffffff
const int maxn=10005;
int dp[maxn];
char a[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",a);
int l1=strlen(a);
fill(dp,dp+l1,INF);
for(int i=0;i<l1;i++)
*lower_bound(dp,dp+l1,a[i])=a[i];
printf("%d\n",lower_bound(dp,dp+l1,INF)-dp);
}
return 0;
}