链接:https://ac.nowcoder.com/acm/problem/13230 来源:牛客网

输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变。如"abc"和"xyz"可以被组合成"axbycz"或"abxcyz"等。 我们定义字符串的价值为其最长回文子串的长度(回文串表示从正反两边看完全一致的字符串,如"aba"和"xyyx")。 需要求出所有可能的C中价值最大的字符串,输出这个最大价值即可

做法

区间dp题,学到的一个点就是如果范围小就考虑开多维去存储,所以dp的思维就是两个串的左右端点,那么就有四种情况,当a串左右相等时,我们看一下缩小一点的a串是否是回文,b串相同,如果a串的开头和b串的结尾一样,考虑把b串字符插入a串,那么就需要看缩小一点,两个端点是否相同,那么a串结尾和b串开头类似,为什么没有a开头和b开头以及a结尾和b结尾?

因为我们是考虑一个区间内两个长度的串是否是回文,而这两种情况不能通过递推得到,其他四种情况,当头尾相同,我们可以考虑一直缩小字串看看是否是回文,而头头相同和尾尾相同并不能得到一个回文。(注意:每次操作数组需要情空,为了不用memset,于是每次先把当前串清为0)

#include<bits/stdc++.h>
#define endl "\n"
#define int long long
/*inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}*/
//dont forget to check long long
//别写重变量名
//记得判越界
//别死磕
//处理字符串删掉关流
//用__int128时记得删掉关流
int f[60][60][60][60];
void slove()
{
    //memset(f,0,sizeof(f));
    int ans=0;
    std::string a,b;
    std::cin>>a>>b;
    a=' '+a;
    b=' '+b;
    int n=a.length()-1;
    int m=b.length()-1;
    for(int len1=0;len1<=n;len1++)
    {
        for(int len2=0;len2<=m;len2++)
        {
            for(int i=1,j=len1+i-1;j<=n;i++,j++)
            {
                for(int l=1,r=len2+l-1;r<=m;l++,r++)
                {
                    if(len1+len2<=1) f[i][j][l][r]=1;
                    else
                    {
                        f[i][j][l][r]=0;
                        if(a[i]==a[j]&&len1>0)
                        {
                            if(f[i+1][j-1][l][r]) f[i][j][l][r]=1;
                        }
                        if(a[j]==b[l]&&len1>0&&len2>0)
                        {
                            if(f[i][j-1][l+1][r]) f[i][j][l][r]=1;
                        }
                        if(a[i]==b[r]&&len1>0&&len2>0)
                        {
                            if(f[i+1][j][l][r-1]) f[i][j][l][r]=1;
                        }
                        if(b[l]==b[r]&&len2>0) 
                        {
                            if(f[i][j][l+1][r-1]) f[i][j][l][r]=1;
                        }
                    }
                    if(f[i][j][l][r]) ans=std::max(ans,len1+len2);
                }
            }
        }
    }
     //std::cout<<a[n]<<' '<<b[m]<<endl;
    std::cout<<ans<<endl;
}
signed main()
{
    int T; 
    std::cin>>T;
    while(T--)    {
        slove();
    }

    return 0;
}

!!!!!!!为了从1下表开始可以在前面加一个空格,但最后一个元素的下标还是字符串长度-1,切记!!!!!