最长公共子序列与最长公共字串

一.求解最长公共子序列(LongestCommon Susequence)

   问题描述:字符串的字符的相对顺序一致的最长字串,如 “adaskas“,”qascdccasa“->”adaa”

   基本思想:动态规划

           If(X[i]=Y[j])  LCS[i,j]=LCS[i-1][j-1];

//如果当前字符相同,则此时最长子序列向前各退一位

           Else if(X[i]!=y[j])  LCS=max(LCS[i-1][j],LCS[i][j-1]);

//如果当前字符不同,则此时最长子序列为分别各退一位的最大值

   伪代码:

          C[]数字只是记录当前最长子序列的长度,B[]则是记录最长子序列寻找的方向

           M=length(X);n=length(Y)

            For(i=1:m)  B[0][i]=0;

            For(i=1:n)   B[i][0]=0;//一个字符串与长度为0的字符串的公共子序列必为0

           For(i=1:m)

               For(j=1:n)

                   If(X[i]==Y[j])

                        B[i][j]=B[i-1][j-1];  C[i][j]=”1”//1代表左上方,2:左 3:上

                   Else if(B[i-1][j]>B[i][j-1])  //B[i][j]=max(B[i-1][j],B[i][j-1];

                         B[i][j]=B[i-1][j];    C[i][j]=”3”

                   Else B[i][j]=B[i][j-1];      C[i][j]=”2”

            此时B矩阵最右下角的数字便是最大公共子序列的之长度

             如果要输出该子序列时只需要在C[]矩阵中当按照方向向下寻找,当B[i][j]=’1’时输出即可,

     时间复杂度:O(mn);

代码:

  #include<iostream>

#include<string>

#include<algorithm>

usingnamespace std;

int main(){

    char str1[] = "abcde";

    char str2[] = "abeefcdeghj";

    int data[50][50];

    int B[50][50];

    int len1 =strlen(str1);

    int len2 =strlen(str2);

    //cout << len1 << endl;

    for (int i = 0; i < 50;i++)

         data[i][0]= data[0][i] = 0;

    int maxer;

    for(int i=1;i<=len1;i++)

         for (int j = 1; j <=len2; j++)

         {

         /*  maxer =max(data[i][j-1], data[i-1][j]);

             if(str1[i - 1] == str2[j - 1])

                  data[i][j]= maxer + 1;

             else

                  data[i][j]= maxer;

         */

             if (str1[i - 1] !=str2[j - 1])

                  if (data[i][j - 1]> data[i - 1][j])

                  {

                      data[i][j]= data[i][j - 1];

                      B[i][j]= 2;//1代表左上,2代表左,3代表上,

                  }

                  else

                  {

                      data[i][j]= data[i][j - 1];

                      B[i][j]= 3;//1代表左上,2代表左,3代表上,

                  }

             else

             {

                  data[i][j]= max(data[i - 1][j], data[i][j - 1]) + 1;

                  B[i][j]= 1;

             }

            

                 

         }

    for (int i = 0; i <=len1; i++)

    {

         for (int j = 0; j <=len2; j++)

             printf("%d ", data[i][j]);

         printf("\n");

    }

    int i=len1;

    int j = len2;

    string result="",s="";

    while (i !=0&&j!=0)

    {

         if (B[i][j] == 1)

         {

             //printf("%c", str1[i - 1]);

             result.insert(0,s+str1[i-1]);

             i--;

             j--;

         }

         elseif (B[i][j] == 2)

             j--;

         elseif(B[i][j]==3)

             i--;

         else;

    }

    cout<< result<<endl;

    return 0;

}

如果要求解最长公共子串,只需要在B中寻找最大的数字即最长字串的长度,找到后按照对角线逐个输出知道当前值为0即结束

代码:

#include<iostream>

#include<algorithm>

usingnamespace std;

/*

求最长公共子序列:问题描述:求两个字符串中公共的最长字符串长度,只需保持相对顺序连续,不需要连续

  核心代码:

        if (str1[i - 1] == str2[j - 1]) then data[i][j] = data[i - 1][j - 1] +1;

 求最长公共子串(本程序的算法):问题描述:求两个字符串最长的公共连续子串,子串必须是连续的

   核心代码:

        if(str1[i-1]==str2[j-1] then data[i][j] = data[i - 1][j - 1] + 1;

          else data[i][j] = max(data[i - 1][j], data[i][j- 1]);

          必要时也可以记录下最长公共子串的内容,代码中加入以下内容:

           if(str1[i-1]==str2[j-1] then data[i][j] =data[i - 1][j - 1] + 1;  B[i][j]="左上"

           else if(data[i][j-1]>data[i-1][j])  then data[i][j]=data[i][j-1];  B[i][j]="上"

           else   data[i][j]=data[i-1][j];  B[i][j]="左";

 

*/

 

int main(){

    char str1[] = "abcde";

    char str2[] = "abeefcdeghj";

    int data[50][50];

    int len1 =strlen(str1);

    int len2 =strlen(str2);

    //cout << len1 << endl;

    for (int i = 0; i < 50;i++)

         data[i][0]= data[0][i] = 0;

    for(inti=1;i<len1+1;i++)

         for (int j = 1; j <len2+1; j++)

         {

             if (str1[i - 1] ==str2[j - 1])

             {

                  data[i][j]= data[i - 1][j - 1] + 1;

             }

             else

                  data[i][j]= 0;

                  //data[i][j] = max(data[i - 1][j], data[i][j - 1]);

 

         }

    for (int i = 0; i <len1+1; i++)

    {

         for (int j = 0; j<len2+1; j++)

             cout<< data[i][j] <<" ";

         cout<< endl;

    }

 

    return 0;

}

猜你喜欢

转载自blog.csdn.net/sinat_37926416/article/details/80049719