牛客 - 合并回文子串

原题:合并回文子串 (nowcoder.com)

题意:输入两个字符串a和b,要求将其合并成字符串c,同时保持a和b中字符顺序不变,求能合成的最长回文子串长度。

分析:区间dp,具体看代码注解。

题解:

#include <bits/stdc++.h>
using namespace std;
const int N=55;
bool dp[N][N][N][N];//意思是a字符串的i到j和b字符串的k到l是否能组成回文子串
char a[N],b[N];
//因为回文串是左右状态相等,所以判断最左和最右的关系即可
//最左和最右的可能性只有:都为a串,都为b串,左边为a右边为b,左边为b右边为a
//因为相对位置不变,所以可以分开判断a串和b串的最左最右字符关系
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%s%s",a+1,b+1);
        int lena=strlen(a+1),lenb=strlen(b+1);
        int ans=1;
        memset(dp,0,sizeof dp);
        for(int i=0;i<=lena;i++)//枚举a字符串的长度
        {
            for(int j=0;j<=lenb;j++)//枚举b的长度
            {
                for(int sta=1,eda=sta+i-1;eda<=lena;sta++,eda++)
                {//遍历选中的a字符串区间
                    for(int stb=1,edb=stb+j-1;edb<=lenb;stb++,edb++)
                    {//遍历选中的b字符串区间
                        //处理边界情况
                        if(i+j<=1) dp[sta][eda][stb][edb]=1;
                        else
                        {
                            //两边都是a
                            if(a[sta]==a[eda]&&(eda>0))
                            dp[sta][eda][stb][edb]|=dp[sta+1][eda-1][stb][edb];
                            //两边都是b
                            if(b[stb]==b[edb]&&(edb>0))
                            dp[sta][eda][stb][edb]|=dp[sta][eda][stb+1][edb-1];
                            //左边是a,右边是b
                            if(a[sta]==b[edb]&&(edb>0))
                            dp[sta][eda][stb][edb]|=dp[sta+1][eda][stb][edb-1];
                            //左边是b,右边是a
                            if(b[stb]==a[eda]&&(eda>0))
                            dp[sta][eda][stb][edb]|=dp[sta][eda-1][stb+1][edb];
                        }
                        
                        if(dp[sta][eda][stb][edb]) ans=max(ans,i+j);
                    }
                }
            }
        }
        
        cout<<ans<<endl;
    }
    return 0;
}

(如有错误,欢迎礼貌指正。如有疑问,欢迎友好交流。鄙人愚笨,敬请原谅。)

上一篇:题解 数数


下一篇:15.WLAN拓扑介绍_WLAN组成原理