• hdu 4681 String(转载)


    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    #define maxn 1111
    char a[maxn],b[maxn],c[maxn];
    int dp1[maxn][maxn],dp2[maxn][maxn],n,m,len;
    struct node//记录在字符串a,b中,c串的首尾位置
    {
        int x,y;
    };
    void lcs()//求最长公共子序列长
    {
        int i, j,k;
        //从字符串左到右
        for(i=0;i<n;i++)
            for(j=0;j<m;j++)
            if(a[i]==b[j])
                dp1[i+1][j+1]=dp1[i][j]+1;
            else
                dp1[i+1][j+1]=max(dp1[i][j+1],dp1[i+1][j]);
        //从字符串右到左
        for(i=n-1;i>=0;i--)
            for(j=m-1;j>=0;j--)
            if(a[i]==b[j])
                dp2[i+1][j+1]=dp2[i+2][j+2]+1;
            else
                dp2[i+1][j+1]=max(dp2[i+1][j+2],dp2[i+2][j+1]);
    }
    void find(char str[],int n,int &t,node e[])//找到c串在a,b中的首尾位置
    {
        int i,j,k;
        for(i=0;i<n;i++)
        {
            if(str[i]==c[0])
            {
                for(j=i+1,k=1;j<n;j++)
                {
                    if(str[j]==c[k])k++;
                    if(k==len)break;
                }
                if(k==len){e[t].x=i+1;e[t++].y=j+1;}
                else break;
            }
        }
    }
    int main()
    {
        int T,tt=0;
        scanf("%d",&T);
        while(T--)
        {
            memset(dp1,0,sizeof(dp1));
            memset(dp2,0,sizeof(dp2));
            int i,j,k;
            scanf("%s%s%s",a,b,c);
            n=strlen(a);
            m=strlen(b);
            len=strlen(c);
            lcs();
            int ans,num1,num2;
            node e[maxn],f[maxn];
            ans=num1=num2=0;
            find(a,n,num1,e);
            find(b,m,num2,f);
            for(i=0;i<num1;i++)
                for(j=0;j<num2;j++)
                ans=max(ans,dp1[e[i].x-1][f[j].x-1]+dp2[e[i].y+1][f[j].y+1]);
            printf("Case #%d: %d
    ",++tt,ans+len);
        }
        return 0;
    }
    /*
        先求出a,b的最长公共子序列,从开头和末尾开始的都要
        其中dp1[i][j]表示a中第i个字符之前,b中第j个字符之前的最长公共子序列长
        dp2[i][j]表示a中第i个字符之后,b中第j个字符之后的最长公共子序列长
    
        用find找到a中所有c首尾所在位置,在首位置固定的情况下找到末位置最小的即可,因为更长的会使结果值较小,存在结构体重
        同理找到b的
    
        e[i].x,e[i].y,f[j].x,f[j].y
        那么d最长为ans=max(ans,dp1[e[i].x-1][f[j].x-1]+dp2[e[i].y+1][f[j].y+1]+len),
    就是说包含c的部分已经固定,只要加上之前和之后的最长公共子序列长就好了
    */
  • 相关阅读:
    Oracle Drop表并未直接删除 drop table xx purge
    Notepad++使用
    Python使用MySQL数据库
    考驾照科目二科目三要点记录
    Linux中权限(r、w、x)对于目录与文件的意义
    linux之expr命令
    linux下scp
    数字货币和区块链联系
    网站
    关于linux 编程
  • 原文地址:https://www.cnblogs.com/XDJjy/p/3264824.html
Copyright © 2020-2023  润新知