lis 最长上升子序列的二分优化

最长上升子序列

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,m,l,r,a[100001],b[100001]; // b[i]表示的是长度为i的最长上升子序列的结尾的最小值
  4. int main(){
  5. scanf("%d",&n);
  6. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  7. b[m=1]=a[1];
  8. for(int i=2;i<=n;i++){
  9. if(b[m]<a[i]) b[++m]=a[i];
  10. else{
  11. //二分查找第一个大于等于a[i]的元素的下标,即l
  12. l=1,r=m;
  13. while(l<=r){
  14. int mid=l+(r-l)/2;
  15. if(a[i]<=b[mid]) r=mid-1;
  16. else l=mid+1;
  17. }
  18. b[l]=a[i]; //注意:b[l]是一定大于b[l-1]的
  19. }
  20. }
  21. printf("%d",m);
  22. return 0;
  23. }
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,m,a[100001],b[100001];
  4. int main(){
  5. scanf("%d",&n);
  6. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  7. b[m=1]=a[1];
  8. for(int i=2;i<=n;i++){
  9. if(b[m]<a[i]) b[++m]=a[i];
  10. else{
  11. int* it=lower_bound(b+1,b+m+1,a[i]);
  12. *it=a[i];
  13. }
  14. }
  15. printf("%d",m);
  16. return 0;
  17. }

lcs 最长公共子序列

最长公共子序列

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. string a,b;
  4. int ans[1001][1001];
  5. int main(){
  6. cin>>a>>b;
  7. memset(ans,0,sizeof(ans));
  8. for(int i=1;i<=a.length();i++){
  9. for(int j=1;j<=b.length();j++){
  10. if(a[i-1]==b[j-1]){
  11. ans[i][j]=ans[i-1][j-1]+1;
  12. }else{
  13. ans[i][j]=max(ans[i-1][j],ans[i][j-1]);
  14. }
  15. }
  16. }
  17. cout<<ans[a.length()][b.length()];
  18. return 0;
  19. }

若序列中无重复数据,可通过map记录每个数据的位置,然后用二分优化(怎样优化暂且不提)