HDU 1503 Advanced Fruits 由两个字符串组成一个最短新串 (最长公共子串变形)

来源:互联网 发布:网络歌手男伤感歌曲 编辑:程序博客网 时间:2024/04/29 02:42

点击打开链接

题意:给出两个串让你再不破坏每个串的字符顺序的情况下 输出一个由两个串组成的新串(保证新串长度最小)


最长公共子串变形 ,通过最长公共子串的方式找到相同字符的坐标位置,然后通过插入的方式将新串输出

方法一:

#include<bits/stdc++.h>#define INF 0x3f3f3f3f#define MAXN 1000using namespace std;int dp[MAXN][MAXN];struct node{    int x,y;} p[MAXN];char s1[MAXN],s2[MAXN];int vis[1000][1000];int main(){    while(~scanf("%s%s",s1,s2))    {        memset(dp,0,sizeof(dp));        memset(vis,0,sizeof(vis));        int len1=strlen(s1);        int len2=strlen(s2);        int top=1;        p[0].x=0;        p[0].y=0;        for(int i=0; i<len1; i++)        {            for(int j=0; j<len2; j++)            {                if(s1[i]==s2[j])   ///最长公共子序列                {                    dp[i][j]=dp[i-1][j-1]+1;                    p[top].x=i;        ///记录s1[i]与s2[j]相同的坐标                    p[top].y=j;                                        vis[i][j]=top++;   ///记录存放坐标的数组下标                }                else                {                    if(dp[i-1][j]>dp[i][j-1])                    {                        dp[i][j]=dp[i-1][j];                        vis[i][j]=vis[i-1][j];                    }                    else                    {                        dp[i][j]=dp[i][j-1];                        vis[i][j]=vis[i][j-1];                    }                }            }        }                stack<int>Q;   ///将存入的坐标的数组下标reserve反转         int next2=vis[len1-1][len2-1];        while(next2>0)        {            Q.push(next2);            if(p[next2].x-1>=0&&p[next2].y-1>=0)                next2=vis[p[next2].x-1][p[next2].y-1];            else                break;        }                int next1=0,next=0;        int flag=1,i=0,j=0;        while(!Q.empty())            ///将新串输出        {            next=Q.top();            ///相同字符的坐标            Q.pop();            for(i=p[next1].x; i<p[next].x; i++) ///输出中间存在的不相同的字符                printf("%c",s1[i]);             //cout<<endl;            if(flag)            {                if(p[next1].y<p[next].y)         ///防止重复输出公共字符                    printf("%c",s2[p[next1].y]);                flag=0;            }            for(j=p[next1].y+1; j<p[next].y; j++)                printf("%c",s2[j]);            // cout<<endl;            next1=next;        }                if(s1[i]==s2[j])     ///防止重复输出公共字符           j++;        for(i; i<len1; i++)            printf("%c",s1[i]);        for(j; j<len2; j++)            printf("%c",s2[j]);        printf("\n");    }    return 0;}
方法二#include<bits/stdc++.h>int dp[111][111];int pre[111][111];char str1[111],str2[111];void P(int i,int l){if(i==0&&l==0)return ;if(pre[i][l]==1){P(i,l-1);printf("%c",str2[l]);}else if(pre[i][l]==3){P(i-1,l);printf("%c",str1[i]);}else {P(i-1,l-1);printf("%c",str1[i]);}}int main(){int i,l;int len1,len2;while(scanf("%s%s",&str1,&str2)!=-1){len1=strlen(str1);len2=strlen(str2);for(l=len1;l>0;l--)str1[l]=str1[l-1];for(l=len2;l>0;l--)str2[l]=str2[l-1];memset(dp,0,sizeof(dp));memset(pre,0,sizeof(pre));for(l=0;l<=len1;l++)pre[l][0]=3;for(l=0;l<=len2;l++)pre[0][l]=1;for(i=1;i<=len1;i++){for(l=1;l<=len2;l++){if(str1[i]==str2[l]){dp[i][l]=dp[i-1][l-1]+1;pre[i][l]=2;}else if(dp[i][l-1]>dp[i-1][l]){dp[i][l]=dp[i][l-1];pre[i][l]=1;}else{dp[i][l]=dp[i-1][l];pre[i][l]=3;}}}P(len1,len2);printf("\n");}return 0;}



0 0