Question:
求单调递增的LIS的优化方法,不要朴素的,会超时
Solution:
定义状态:
dp[i]:长度为i的最长单调递增子序列的最后一个元素(保证这个元素是最小的,贪心的思路)
状态转移方程:
这个比较难写,我从原理的角度出发,解释一下
我们这里会发现,定义的这个状态一定是一个递增的序列,也就是说,我们在查找的额时候完全可以利用二分查找来优化我们的时间复杂度,二分查找最后返回的是我们第一个大于待查元素的坐标的位置,如果没有,返回总长度的加1的数值大小
Code:
#include"iostream"
#include"cstdio"
#include"cstring"
#define N 10005
using namespace std;
char dp[N];
int len;
int n;
char data[N];
int bs(char k)
{
int left=0;
int right=len-1;
while(left<=right)
{
int mid=(left+right)/2;
if(dp[mid]>k) right=mid-1;
else if(dp[mid]<k) left=mid+1;
else return mid;
}
return left;
}
int main()
{
cin>>n;
while(n--)
{
memset(data,0,sizeof(data));
scanf("%s",data);
dp[0]=data[0];
len=1;
for(int i=1;i<strlen(data);i++)
{
int j=bs(data[i]);
dp[j]=data[i];
if(j+1>len) len=j+1;
}
cout<<len<<endl;
}
return 0;
}