zoukankan      html  css  js  c++  java
  • 最长公共子序列LCS+最长递增子序列LIS+最长递增公共子序列LICS

    最长公共子序列(LCS):两个串s1和s2中取出若干有序位置的字符,使得取出的两个字符串相同的长度的最大值就是LCS

    最长递增子序列(LIS):S的子序列,其中各元素按索引严格单调递增

    最长公共递增子序列(LCIS):上面两者的结合,参考博客https://blog.csdn.net/wall_f/article/details/8279733

    最长上升子序列的O(n^2)复杂度算法,算法的优势在于可以保存算法的转移,可以得出最后的序列。

    代码如下:

     1 #include<iostream>
     2 using namespace std;
     3 #define maxn 100
     4 int n;
     5 //  20 17 2 3 4 1 4 6 9 1 1 2 3 4 9 87 21 23 331 31 44
     6 //   10 1 1 1 1 1 2 2 2 3 3
     7 int a[maxn];
     8 int dp[maxn],from[maxn];
     9 void print (int pos)
    10 {
    11     if(!pos)return;
    12     print(from[pos]);
    13     cout<<a[pos]<<' ';
    14 }
    15 int main()
    16 {
    17     cin>>n;
    18     for(int i=1;i<=n;i++)cin>>a[i];
    19     for(int i=1;i<=n;i++)
    20     {
    21         dp[i]=1;//以i为终止位置的最长上升子序列的长度 
    22         for(int j=1;j<i;j++)
    23         {
    24             if(a[i]>a[j]&&dp[i]<dp[j]+1)    
    25             {
    26                 dp[i]=dp[j]+1;
    27                 from[i]=j;//使dp[i]改变的最后一个位置 
    28             }
    29         }
    30     }
    31     int ans=1,pos=1;
    32     for(int i=1;i<=n;i++)
    33     {
    34         if(dp[i]>ans)
    35         {
    36             ans=dp[i];//记录len改变的最后一个位置
    37             pos=i; 
    38         }
    39     }
    40     cout<<ans<<endl; 
    41     print(pos);
    42 }

    最长上升子序列的O(nlogn)算法, 中间结果无法保存,只能知道最长上升子序列的长度。其中加上一个辅助数组,数组的长度表示的是最长上升子序列的长度,数组中第i个位置保存的数是长度为i的最长上升子序列的末位最小元素,利用了贪心的思想,因为末尾的元素值越小的话留给下一个元素更新的余地就会更大。由于长度为n-1的最长上升子序列的末位元素一定是小于长度为n的最长上升子序列的末位元素,所以辅助数组的元素一定是有序的。

    代码如下:

     1 #include<iostream>
     2 using namespace std;
     3 #define maxn 100
     4 #define INF 0x7ffffff
     5 int n,l,r;
     6 int a[maxn],dp[maxn];//dp[i]表示长度为i的最长上升子序列的末位元素最小值 
     7 int main()
     8 {
     9     cin>>n;
    10     for(int i=1;i<=n;i++)
    11     {
    12         cin>>a[i];
    13         dp[i]=INF;
    14     }
    15     dp[1]=a[1];
    16     int len=1;
    17      for(int i=2;i<=n;i++)
    18      {
    19          int mid;
    20          l=0,r=len;
    21          if(a[i]>dp[len])dp[++len]=a[i];
    22          else 
    23          {                              //二分查找 ,查找第一个大于a[i]的位置 
    24              while(l<r)
    25              {
    26                  mid=(l+r)/2;
    27                  if(dp[mid]>a[i])r=mid;
    28                  else {
    29                      l=mid+1;
    30                  }
    31               } 
    32         }
    33          dp[l]=min(dp[l],a[i]);
    34      }
    35      cout<<len<<endl;
    36  } 

    最长公共子序列算法如下:(包括对路径的保存)

     1 #include <cstdio>
     2 #include <iostream>
     3 using namespace std;
     4 int dp[1000][1000];
     5 int main()
     6 {
     7     string a,b;
     8     while(cin>>a>>b)
     9     {
    10         for(int i=1;i<=a.size();i++)
    11         for(int j=1;j<=b.size();j++)
    12         {
    13            if(a[i-1]==b[j-1])dp[i][j]=dp[i-1][j-1]+1;
    14            else  dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    15         }
    16 
    17        char path[1000];
    18         for(int aa=a.size(),bb=b.size(),num=1;aa>=1&&bb>=1;)
    19         {
    20             if(a[aa-1]==b[bb-1])
    21             {
    22                 path[num++]=a[aa-1];
    23                 aa--,bb--;
    24             }
    25             else
    26             {
    27                 if(dp[aa-1][bb]>dp[aa][bb-1])
    28                     aa--;
    29                 else bb--;
    30             }
    31         }
    32         cout<<dp[a.size()][b.size()]<<endl;
    33         for(int i=dp[a.size()][b.size()];i>=1;i--)
    34             cout<<path[i]<<" ";
    35         cout<<endl;
    36     }
    37     return 0;
    38 }

    最长公共上升子序列算法:

     1 #include<iostream>
     2 #include<cstring> 
     3 #include<string>
     4 using namespace std;
     5 
     6 int max(int a,int b)
     7 {
     8     return a>b?a:b;
     9 }
    10 
    11 int a[1010],b[1010];
    12 int f[1010],n,m;
    13 
    14 int LCIS()
    15 {
    16     int i,j,MAX;
    17     memset(f,0,sizeof(f));
    18     for(i=0;i<n;i++)
    19     {
    20         MAX=0;
    21         for(j=0;j<m;j++)
    22         {
    23             if(a[i]>b[j])MAX=max(MAX,f[j]);
    24             if(a[i]==b[j])f[j]=MAX+1; 
    25         }
    26     }
    27     int ans=0;
    28     for(i=0;i<m;i++)
    29         ans=max(ans,f[i]);
    30     return ans;
    31 }
    32 
    33 int main()
    34 {
    35     int t,i,j;
    36         scanf("%d",&n);
    37         for(i=0;i<n;i++)
    38         {
    39             scanf("%d",&a[i]);
    40         }
    41         scanf("%d",&m);
    42         for(j=0;j<m;j++)
    43         {
    44             scanf("%d",&b[j]);
    45         }
    46         printf("%d
    ",t=LCIS());
    47         if(t)
    48             printf("
    ");
    49       for(int i=0;i<t;i++)cout<<f[t]<<endl;
    50     return 0;
    51 }
  • 相关阅读:
    Spring之Condition(二)在哪里解析的
    SpringBoot启动跟代码过程
    Spring之Condition(一)
    Kafka之 vm.max_map_count
    Redis常见面试题
    Redis为什么快
    TCP一个包多大
    场景问题
    这是一个测试
    小程序-使用django-drf开接口的步骤
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12679166.html
Copyright © 2011-2022 走看看