Advanced Fruits
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 1944   Accepted: 967   Special Judge

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

Source

题意:

给你两个长度不超过100的字符串A,B。

要你找出一个最短的字符串C。

使得A,B都是C的子序列(不一定是子串).

思路:

開始看题目里面写的是sub-strings然后看例子百思不得其解。没办法。大胆如果出题人这两个概念分不清。思索片刻后想出了O(n^3)的算法。vis[k][i][j]表示C串长为k时包括了A串的前i-1个字符和B串的前j-1个位置。

那么

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

vis[k+1][i+1][j+1]=1;

else

vis[k+1][i+1][j]=1,vis[k+1][i][j+1]=1;

然后找到最小的k即可了。

比赛的时候各种犯傻。调试了非常久才调出来。

下来又想了下这道题。

认为先前的做法简直可爱到极致。为何生拉硬扯加个k.直接dp[i][j]表示包括了A串的前i-1个字符和B串的前j-1个位置的C串的最短长度。

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

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

else

dp[i][j]=min(dp[i][j-1],dp[i-1][j])+1;

然后记录转移的方向就好了。

具体见代码:

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
int dp[150][150],path[150][150];
char sa[150],sb[150];
void print(int i,int j)
{
if(i==0&&j==0)
return;
if(path[i][j]==1)
{
print(i-1,j);
printf("%c",sa[i]);
}
else if(path[i][j]==-1)
{
print(i,j-1);
printf("%c",sb[j]);
}
else
{
print(i-1,j-1);
printf("%c",sa[i]);
}
}
int main()
{
int i,j,la,lb; while(~scanf("%s%s",sa+1,sb+1))
{
la=strlen(sa+1);
lb=strlen(sb+1);
for(i=1;i<=la;i++)
dp[i][0]=i,path[i][0]=1;
for(i=1;i<=lb;i++)
dp[0][i]=i,path[0][i]=-1;
for(i=1;i<=la;i++)
for(j=1;j<=lb;j++)
{
dp[i][j]=INF;
if(sa[i]==sb[j])//相等仅仅用添加一个字符
dp[i][j]=dp[i-1][j-1]+1,path[i][j]=0;
else
{
if(dp[i][j-1]<dp[i-1][j])//添加sb[j]
dp[i][j]=dp[i][j-1]+1,path[i][j]=-1;
else//添加sa[i]
dp[i][j]=dp[i-1][j]+1,path[i][j]=1;
}
}
print(la,lb);
printf("\n");
}
return 0;
}

比赛的做法:

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int vis[210][150][150],path[210][150][150];
char sa[150],sb[150];
void print(int st,int i,int j)
{
//printf("st %d i %d j %d\n",st,i,j);
if(st==1)
{
if(path[st][i][j]==1)
printf("%c",sa[i-1]);
else if(path[st][i][j]==-1)
printf("%c",sb[j-1]);
else
printf("%c",sa[i-1]);
return;
}
if(path[st][i][j]==1)
{
print(st-1,i-1,j);
printf("%c",sa[i-1]);
}
else if(path[st][i][j]==-1)
{
print(st-1,i,j-1);
printf("%c",sb[j-1]);
}
else
{
print(st-1,i-1,j-1);
printf("%c",sa[i-1]);
}
}
int main()
{
int la,lb,i,j,k,len;
while(~scanf("%s%s",sa,sb))
{
la=strlen(sa);
lb=strlen(sb);
memset(vis,0,sizeof vis);
len=la+lb;
vis[1][1][0]=vis[1][0][1]=1,path[1][1][0]=1,path[1][0][1]=-1;
if (sa[0]==sb[0]) vis[1][1][1]=1,path[1][1][1]=0;
for(k=1;k<=len;k++)
{
if(vis[k][la][lb])
break;
//printf("k %d\n",k);
for(i=0;i<=la;i++)
for(j=0;j<=lb;j++)
{
if(!vis[k][i][j])
continue;
//printf("%d %d\n",i,j);
if(i<la&&j<lb&&sa[i]==sb[j]&&!vis[k+1][i+1][j+1])
vis[k+1][i+1][j+1]=1,path[k+1][i+1][j+1]=0;
else
{
if(!vis[k+1][i+1][j])
vis[k+1][i+1][j]=1,path[k+1][i+1][j]=1;
if(!vis[k+1][i][j+1])
vis[k+1][i][j+1]=1,path[k+1][i][j+1]=-1; }
}
}
//printf("k %d\n",k);
print(k,la,lb);
printf("\n");
}
return 0;
}

poj 2264 Advanced Fruits(DP)的更多相关文章

  1. LCS(打印全路径) POJ 2264 Advanced Fruits

    题目传送门 题意:两个字符串结合起来,公共的字符只输出一次 分析:LCS,记录每个字符的路径 代码: /* LCS(记录路径)模板题: 用递归打印路径:) */ #include <cstdio ...

  2. hdu 1503:Advanced Fruits(动态规划 DP & 最长公共子序列(LCS)问题升级版)

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  3. 最长公共子序列(加强版) Hdu 1503 Advanced Fruits

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  4. Advanced Fruits(HDU 1503 LCS变形)

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  5. Advanced Fruits(好题,LCS的模拟)

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  6. HDU-1053:Advanced Fruits(LCS+路径保存)

    链接:HDU-1053:Advanced Fruits 题意:将两个字符串合成一个串,不改变原串的相对顺序,可将相同字母合成一个,求合成后最短的字符串. 题解:LCS有三种状态转移方式,将每个点的状态 ...

  7. poj 2264(LCS)

    Advanced Fruits Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2158   Accepted: 1066   ...

  8. hdu 1503 Advanced Fruits(最长公共子序列)

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  9. hdu 1503 Advanced Fruits 最长公共子序列 *

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

随机推荐

  1. Leetcode 337.大家结舍III

    打家劫舍III 在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区.这个地区只有一个入口,我们称之为"根".除了"根"之外,每栋房子有且只有 ...

  2. Leetcode 335.路径交叉

    路径交叉 给定一个含有 n 个正数的数组 x.从点 (0,0) 开始,先向北移动 x[0] 米,然后向西移动 x[1] 米,向南移动 x[2] 米,向东移动 x[3] 米,持续移动.也就是说,每次移动 ...

  3. zoj 2104 Let the Balloon Rise

    Let the Balloon Rise Time Limit: 2 Seconds      Memory Limit: 65536 KB Contest time again! How excit ...

  4. [转]常见linux命令用法介绍

    su switch user 用途:用于用户之间的切换 格式: su - USERNAME切换用户后,同时切换到新用户的工作环境中 su USERNAME切换用户后,不改变原用户的工作目录,及其他环境 ...

  5. 雅图CAD

    今天培训了雅图CAD. 由辅助线确定下一步的位置,是个好思想.

  6. hdu 4764 巴什博弈

    Stone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  7. 九度oj 题目1354:和为S的连续正数序列

    题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久, ...

  8. 原生 ajax get请求数据

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. BZOJ 3850: ZCC Loves Codefires【贪心】

    Though ZCC has many Fans, ZCC himself is a crazy Fan of a coder, called "Memset137". It wa ...

  10. P1026 统计单词个数 (动态规划)

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...