對LCS進行儲存

E - Advanced Fruits
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

The company "21st Century Fruits" has specialized in creating new sorts of fruits by transferring genes from one fruit into the genome of another one. Most times this method doesn't work, but sometimes, in very rare cases, a new fruit emerges that tastes like a mixture between both of them. 
A big topic of discussion inside the company is "How should the new creations be called?" A mixture between an apple and a pear could be called an apple-pear, of course, but this doesn't sound very interesting. The boss finally decides to use the shortest string that contains both names of the original fruits as sub-strings as the new name. For instance, "applear" contains "apple" and "pear" (APPLEar and apPlEAR), and there is no shorter string that has the same property. 

A combination of a cranberry and a boysenberry would therefore be called a "boysecranberry" or a "craboysenberry", for example. 

Your job is to write a program that computes such a shortest name for a combination of two given fruits. Your algorithm should be efficient, otherwise it is unlikely that it will execute in the alloted time for long fruit names. 

Input

Each line of the input contains two strings that represent the names of the fruits that should be combined. All names have a maximum length of 100 and only consist of alphabetic characters. 

Input is terminated by end of file. 

Output

For each test case, output the shortest name of the resulting fruit on one line. If more than one shortest name is possible, any one is acceptable. 

Sample Input

apple peach
ananas banana
pear peach

Sample Output

appleach
bananas
pearch


這道題的對命名的規則本身就描述得不是很清楚,我都是看別人的代碼纔看懂的。代碼大體思路都懂,但是有些細節地方卻一知半解。不過感覺那個倒序存LCS的代碼應該是個模板。


代碼:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

#define MaxSize 105
#define inf 0x3f3f3f3f
#define LL long long int

int n,m,cnt;
int dp[MaxSize][MaxSize];
char s1[MaxSize],s2[MaxSize];

struct node
{
  int i,j;
  char c;

} len[MaxSize];

void get_dp()//求出LCS長度
{
  n=strlen(s1+1);//注意s1和s2的開始地址,strlen是從給的地址一直掃到'\0',如果這裏寫成了strlen(s1),那麼第一個就是'\0',n就是0了
  m=strlen(s2+1);

  for(int i=1; i<=n; i++)
    {
      for(int j=1; j<=m; j++)
        {
          if(s1[i]==s2[j])
            dp[i][j]=dp[i-1][j-1]+1;

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

void get_LCS()//儲存LCS裏面的字母
{
  int i=n;
  int j=m;
  cnt=1;

  while(i!=0 && j!=0)//倒着去找。這樣能理解,沒問題,但是不知道能不能用正序找。
    {
      if(s1[i]==s2[j] && dp[i][j] == dp[i-1][j-1]+1)
        {
          len[cnt].i=i;
          len[cnt].j=j;
          len[cnt].c=s1[i];

          cnt++;

          i--;
          j--;
        }

      else if(dp[i-1][j] > dp[i][j-1])//說明i-1之前有和s2[j]一樣的字母,於是i就慢慢退,去找那個字母,那就是第一次讓dp加1的公共字母(感覺上好像是這樣,實際上並沒有想明白)
        i--;

      else
        j--;
    }
}

int main()
{
  while(~scanf("%s%s",s1+1,s2+1))//從數組的1位置開始,會省去關於dp下標的不少麻煩
    {
        memset(dp,0,sizeof(dp));

        get_dp();

        get_LCS();

        int i=1;
        int j=1;
        for(int k=cnt-1;k>=1;k--)
        {
            while(i!=len[k].i)//將第一串的輸出位置標記慢慢調整到LCS字母之前
            {
                printf("%c",s1[i]);

                i++;
            }
            while(j!=len[k].j)//將第二串的輸出位置標記慢慢調整到LCS字母之前
            {
                printf("%c",s2[j]);

                j++;
            }

            printf("%c",len[k].c);//輸出當前的LCS字母

            i++;
            j++;
        }

        for(int k=i;k<=n;k++)//把第一串LCS之後的字符串輸出來
        printf("%c",s1[k]);

        for(int k=j;k<=m;k++)//把第二串LCS之後的字符串輸出來
        printf("%c",s2[k]);

        printf("\n");
    }

  return 0;
}//FROM CJZ



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章