这道题的思路很简单,就是普通的dp,甚至比起单个字符串判断最大子回文长度还要简单。但是在细节上有相当多的地方需要注意

由于数据量是50所以说可以用一些时间复杂度比较神秘的dp方法,这里我们模仿普通单个字符串回文的求法,设一个四维dp数组,说明a的[l1,r1]区间与b的[l2,r2]区间组成的字符串最大长度是多少

但是这样又出现了新的问题:我们的dp只会积累数值而不会具体的去记录配对方法,所以dp存储最大子串长度行不通。考虑到我们会遍历所有可能的组合方式,我们可以转而存储是否可以组成一个回文串。在遍历的过程中维护ans即可

对于初始条件:如果长度为1那肯定为1,对于状态转移:只有可能四种情况,开头结尾都来自于a或者b,开头a结尾b或者开头b结尾a。如果相等并且有一种方法使得剩余的内部子串也可以组成回文,则更新ans与当前dp。一个很正常的思路

对于实现的过程,有几点是我犯的错误,这至少浪费了我三四个小时,在这里写出来作为参考

1:出于复杂度,我们开四维数组肯定不会用vector,而且我们使用len方法的话,r = l + len - 1的r是有可能成为负数的,要小心负数索引的话:可以使用经典1-based,类似于栈问题我们放入一个哨兵元素防止为空出错,我们对于a和b也可以加上一个哨兵元素

a = "0" + a;
b = "0" + b;

对于r = l + len - 1,最小也只会为0,就不会因为负数索引而产生神秘错误了

2:书接上文,我们使用了哨兵元素,那么实际长度会+1,这对于我们的四层循环会产生影响,对于len而言,长度需要在.size()的基础上减一。对于枚举左侧元素l,当然r为l + len - 1,但是考虑到1-based,边界条件应该为l + len - 1 <= .size() - 1(这里的size比起原来的1-based而言也还是大了,我一开始就是这里出现问题的)

AC代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;

//哇子回文串问题耶。但好像也不是那么板子,可能要找到新的dp方式。。。。。。
//50*50的数据量,又加上dp,可以用一点很神秘的时间复杂度

signed main() 
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int T; 
    
    cin >> T;
    
    for(int t = 0;t < T;t++)
    {        
        string a,b;
        
        cin>>a>>b;
        
        a = "0" + a;
        
        b = "0" + b;
        
        int ans = 1;
        
        int n = max(a.size(),b.size());

        int dp[60][60][60][60];
        
        memset(dp,0,sizeof(dp));
        
        //对于dp的状态转移,由用户的遍历顺序来负责
        
        for(int len1 = 0;len1 < a.size();len1++)
        {
            for(int len2 = 0;len2 < b.size();len2++)
            {
                for(int l1 = 1;l1 + len1 <= a.size();l1++)
                {
                      for(int l2 = 1;l2 + len2 <= b.size();l2++)
                      {
                          int r1 = l1 + len1 - 1;
                          
                          int r2 = l2 + len2 - 1;
                          
                          if(len1 + len2 <= 1)
                          {
                              dp[l1][r1][l2][r2] = 1;
                              
                              continue;
                          }
                          
                          if(a[l1] == a[r1])
                          {
                              if(dp[l1 + 1][r1 - 1][l2][r2] == 1)
                              {
                                  dp[l1][r1][l2][r2] = 1;
                                  
                                  ans = max(ans,len1 + len2);
                              }
                          }
                          
                          if(b[l2] == b[r2])
                          {
                              if(dp[l1][r1][l2 + 1][r2 - 1] == 1)
                              {
                                  dp[l1][r1][l2][r2] = 1;
                                  
                                  ans = max(ans,len1 + len2);
                              }                              
                          }
                          
                          if(a[l1] == b[r2])
                          {
                              if(dp[l1 + 1][r1][l2][r2 - 1] == 1)
                              {
                                  dp[l1][r1][l2][r2] = 1;
                                  
                                  ans = max(ans,len1 + len2);
                              }                             
                          }
                          
                          if(b[l2] == a[r1])
                          {
                              if(dp[l1][r1 - 1][l2 + 1][r2] == 1)
                              {
                                  dp[l1][r1][l2][r2] = 1;
                                  
                                  ans = max(ans,len1 + len2);
                              }                            
                          }
                      }
                }
            }
        }
        
        cout<<ans<<endl;
    }
    
    return 0;
}