算法:最长递增子序列、最长公共子串

来源:互联网 发布:小苍零食淘宝店 编辑:程序博客网 时间:2024/06/10 18:28
#include<iostream>#include<cstring>#define MAXSEQUENCE 1000#define MAXDIF 1000using namespace std;void Print_LCS(int (*rec)[100],int a[], int b[], int i, int j);//---------最长递增子序列-----------//动态规划 O(n*n)   递推式:len[i] = max{ len[k]+1 | a[k]< a[i] , 0<=k<i}int LIS(int a[],int n){int len[MAXSEQUENCE];len[0]=1;for(int i=1;i<n;i++){len[i]=1;//此处是O(n),可用二分搜索来对此处改进 B数组,//下标是最大子序列长度,值是最小的最末元素,巧妙!!! (即下面的该函数LIS_bin)for(int j=0;j<i;j++)if(a[j]<a[i]&&len[j]+1>len[i])len[i]=len[j]+1;  }int maxlen=0;    for(int i=0;i<n;i++)        if(len[i]>maxlen)            maxlen=len[i];return maxlen;}//动态规划O(nlogn),求最长递增子串的长度更快捷,难以输出最长子串。int LIS_bin(int a[],int n) {int B[MAXSEQUENCE];    int len=1;B[0]=a[0]; //注意此处的赋值,不是B[0]=0; for(int i=1;i<n;i++){int left=0, right=len-1;while(left<=right){ //O(logn) 找到大于等于ai的第一个元素 ,返回时left指向 int m=(left+right)/2;if(B[m]<a[i]) left=m+1;else right=m-1;}B[left]=a[i];    //更新 if(left+1>len) len++;  //看是否长度要增大} return len;}//o(n*n),但存储空间从o(n)增大到o(n*maxdis),maxdis为所有元素的最大差值,有没有更好的方法? int  LIS_EqualDif(int a[], int n) {  n=n;int len[MAXSEQUENCE][MAXDIF]; //当差增较大时,很快存储空间就不能定义了 //求最大差值int MaxVal=a[0], MinVal=a[0];for(int i=1;i<n;i++){if(MaxVal<a[i]) MaxVal = a[i];else if(MinVal>a[i])MinVal = a[i];}                                       int MaxDif = MaxVal - MinVal;memset(len,0,n*(MaxDif+1)*sizeof(int));  for(int i=1;i<n;i++){for(int j=0;j<i;j++){int dis=a[i]-a[j];if(dis>=0) //注意是等差,所以相等也算 len[i][dis] = len[j][dis] + 1;}}int result=0;for(int i=0;i<n;i++)for(int j=0;j<=MaxDif;j++)if(result<len[i][j])result = len[i][j];return result+1;}//---------最长公共子序列-----------//动态规划,O(mn) ,a.length=m, b.length=n int LCS(int a[], int n,int b[],int m){int len[MAXSEQUENCE][MAXSEQUENCE]; //从下标1开始,记录i,j之前的最大长度 for(int i=0;i<n;i++)len[i][0]=0;for(int i=0;i<m;i++)len[0][i]=0;int i,j;for(i=0;i<n;i++){for(j=0;j<m;j++){if(a[i]==b[j]){  //如果相等 len[i+1][j+1]=len[i][j]+1;}else{// 不相等 if( len[i][j+1]>len[i+1][j] )len[i+1][j+1]=len[i][j+1];elselen[i+1][j+1]=len[i+1][j];}}}return len[i][j];}//分治,最长公共子串,O(2^n) ,有太多的重复计算,导致复杂度呈指数级增长 int LCS_recur(int a[], int n, int b[],int m){if(m==0||n==0)return 0;if(a[n-1]==b[m-1]){return LCS_recur(a,n-1,b,m-1)+1;}else{int tmp1=LCS_recur(a,n-1,b,m);int tmp2=LCS_recur(a,n,b,m-1);if(tmp1>tmp2)return tmp1;elsereturn tmp2;} }int main(){loop: int a[MAXSEQUENCE],b[MAXSEQUENCE],n,m;//LISprintf("n: ");scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]);printf("LIS: %d\n",LIS(a,n));printf("LIS_bin: %d\n",LIS_bin(a,n));printf("LIS_EqualDif: %d\n",LIS_EqualDif(a,n));//LCSprintf("m: ");scanf("%d",&m);for(int i=0;i<m;i++)scanf("%d",&b[i]);printf("LCS: %d\n",LCS(a,n,b,m));printf("LCS_recur: %d\n",LCS_recur(a,n,b,m));goto loop;     return 0;   } 


 

原创粉丝点击