动态规划之最长公共子序列/最长公共子串

最长公共子序例 和最长公共子串

最长公共子序例 与最长公共子串 的区别  子串要求在原字符串中是连续的,而子序列则只需保持相对顺序一致,并不要求连续。例如X = {a, Q, 1, 1}; Y = {a, 1, 1, d, f}那么,{a, 1, 1}是X和Y的最长公共子序列,但不是它们的最长公共字串。

一、最长公共子序例

 

只求最长子序例长度

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int arr[499][499];
int main() {
  string str, str1;
  while (cin>>str>>str1) {
    memset(arr, 0, sizeof(arr));
       int k = str.size();
       int l = str1.size();
       int count = 0;
       for (int i = 0; i < k; i++) {
           for (int j = 0; j < l; j++) {
               if (str[i] == str1[j]) {
                  arr[i+1][j+1] = arr[i][j] + 1;            
                }else {
                  arr[i+1][j+1] = max(arr[i+1][j],arr[i][j+1]);
                }
            }
        }
        cout<<arr[k][l]<<endl;
  } 
}

二、最长公共子串

 最长公共子串与最长公共子序例的不同是str[i] != str1[j] 的时候  arr[i][j] = 0 而不是 arr[i][j] = max(arr[i-1][j],arr[i][j-1]);

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int arr[499][499];
int main() {
  string str, str1;
  while (cin>>str>>str1) {
    memset(arr, 0, sizeof(arr));
       int k = str.size();
       int l = str1.size();
       int maxsum = 0;
       for (int i = 0; i < k; i++) {
           for (int j = 0; j < l; j++) {
               if (str[i] == str1[j]) {
                 arr[i+1][j+1] = arr[i][j] + 1;
                 if (maxsum < arr[i+1][j+1])
                    maxsum = arr[i+1][j+1]            
                }else {
                  arr[i+1][j+1] = 0;
        }
            }
        }
        cout<<maxsum<<endl;
  } 
}

三、最长递增子序例

设长度为N的数组为{a0,a1, a2, ...an-1),则假定以aj结尾的数组序列的最长递增子序列长度为L(j),则L(j)={ max(L(i))+1, i<j且a[i]<a[j] }。也就是说,我们需要遍历在j之前的所有位置i(从0到j-1),找出满足条件a[i]<a[j]的L(i),求出max(L(i))+1即为L(j)的值。最后,我们遍历所有的L(j)(从0到N-1),找出最大值即为最大递增子序列。时间复杂度为O(N^2)。

/*
有毒数组开到100超时开1000超内存 
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int arr[100000];
int a[100000];
int main() {
  int n; 
  while (scanf("%d", &n) != EOF) {
     memset(arr, 0, sizeof(arr));
     for (int i = 0; i < n; i++) scanf("%d", &a[i]);
     int max = 0;
     for (int i = 1; i < n; i++) {
       for (int j = 0; j < i; j++) {
           if (a[j] < a[i] && arr[j] + 1 > arr[i]) {
              arr[i] = arr[j] + 1;
              if (arr[i] > max) max = arr[i];        
           }
       }
      }
    printf("%d\n", max+1);
    } 
}

最长递增子序例解法二

   二分法

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
  
#define N 9 //数组元素个数  
int array[N] = {2, 1, 6, 3, 5, 4, 8, 7, 9}; //原数组  
int B[N]; //在动态规划中使用的数组,用于记录中间结果,其含义三言两语说不清,请参见博文的解释  
int len; //用于标示B数组中的元素个数  
  
int LIS(int *array, int n); //计算最长递增子序列的长度,计算B数组的元素,array[]循环完一遍后,B的长度len即为所求  
int BiSearch(int *b, int len, int w); //做了修改的二分搜索算法  
  
int main()  
{  
    printf("LIS: %d\n", LIS(array, N));  
  
    int i;  
    for(i=0; i<len; ++i)  
    {  
        printf("B[%d]=%d\n", i, B[i]);  
    }  
  
    return 0;  
}  
  
int LIS(int *array, int n)  
{  
    len = 1;  
    B[0] = array[0];  
    int i, pos = 0;  
  
    for(i=1; i<n; ++i)  
    {  
        if(array[i] > B[len-1]) //如果大于B中最大的元素,则直接插入到B数组末尾  
        {  
            B[len] = array[i];  
            ++len;  
        }  
        else  
        {  
            pos = BiSearch(B, len, array[i]); //二分查找需要插入的位置  
            B[pos] = array[i];  
        }  
    }  
  
    return len;  
}  
  
//修改的二分查找算法,返回数组元素需要插入的位置。  
int BiSearch(int *b, int len, int w)  
{  
    int left = 0, right = len - 1;  
    int mid;  
    while (left <= right)  
    {  
        mid = left + (right-left)/2;  
        if (b[mid] > w)  
            right = mid - 1;  
        else if (b[mid] < w)  
            left = mid + 1;  
        else    //找到了该元素,则直接返回  
            return mid;  
    }  
    return left;//数组b中不存在该元素,则返回该元素应该插入的位置  
}  

四’最大子串和

void solve() {
  int sum = 0;
  int max = -0xfff;
  for (int i = 0; i < n; i++) {
    sum += arr[i];
    if (sum > max) {
      max = sum;
    }else if (sum < 0) {
      sum = 0;
    }
  }
} 

 

posted @ 2017-11-12 17:03  白丁一枚  阅读(263)  评论(0编辑  收藏  举报