粗体内容 说句实话我的能力还停留在那种二维线性/区间dp上...所以做这个题真的有点吃力,不过这个题的转态转移方程还是比较好推.我
推了方程到我看别人提交的代码,我浪费了6h...第一次推出方程写不出题,,,怎么说 尽量自己想...就是这个心态,我推出方程后不会处理...
一直输出别的数或者啥玩意的,最多输出的就是0...我给大家讲讲方程具体咋推的吧...然后再教大家咋写的(这个是看的最原始的那个大佬代码
以前还以为推出方程的dp就能写出来,果然还是我太年轻了hhh...
回归正题;不知道大家有没有做过牛客的那个括号匹配..和这个类似,就是个匹配问题..首先咋想到是用dp的呢?因为我太菜...学过的算法能用的
就贪心和dp可能还有二分.其实是直觉,因为dp就是减少暴力次数的一种算法..有点记忆化吧..50^50这个题最暴力的一个想法..然后讲讲为啥开
4维..因为数据50,遇到5000肯定二维,遇到1e5以上的要不就是一维要不就是一维带个状态..50要不3维要不4维嘛..然后根据题意4维最合适..
dp[i j][k l] i j为字符串a中i j的部分 k l为字符串b中k~l部分能否构成回文串
现在我要判断i j部分能否与k l部分构成回文串 dp无非就是转态转移因为是匹配嘛,所以很容易联想到dp[1][1][0][0]=1和dp[0][0][1][1]=1;
然后我们就会想怎么从上一个转态转移到->下一个转态;无非就两种情况现在的处境下来了一个a[j]或者b[l]都是从少的一步一步积累的嘛
先讲讲假如来a[j],因为位于a[]当前最后一个位子肯定是与最前面的a[i]和b[k]判断是否相等..假如a[j]==a[i]意味着我有可能组成回文串了
但是呢..我还要保证中间的也能组成回文串..假设我要转移的到的转态是dp[i][j][k][l]那我现在这个转态就是dp[i][j-1][k][l]..现在已经有了
a[j]==a[i]那我要满足就是dp[i+1][j-1][k][l]=1;->(这个就是保证中间的能否构成回文串)..其他三个方程和这个是一样的,我就不解释了...
下面讲讲我不会的4个for...4个for啊啊啊啊啊啊啊啊啊啊啊啊啊
我4个for写的i j k l这就是我写不出来的原因(因为平时就是这样写的嘛..)..第一个的for写的a数组中连续的个数 第二个for写的b数组中连续的个数 第三个for就是写的a数组的起点和终点 第四个for写的就是b数组的起点和终点..然后把他们进行一个一个的匹配...就没了

#include<bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb push_back
#define inf 1329103910
typedef long long ll;
const ll mod=1e9+7;
const ll N=55;
const double eps=1e-7;
using namespace std;
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b) { return a*b/gcd(a,b);    }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a = (a*a)%p;b >>= 1;}return ans%p;}
ll Inv(ll x){ return qp(x,mod-2,mod);}
ll C(ll n,ll m){if (m>n) return 0;ll ans = 1;for (int i = 1; i <= m; ++i) ans=ans*Inv(i)%mod*(n-i+1)%mod;return ans%mod;}
int dp[N][N][N][N];
/*
    四个维度分别用i j l k表示
    分别表示 A中i~j 和 B中k~l
*/
char a[N];
char b[N];
int main()
{
    int t,ans=0,n,m;
    cin>>t;
    while(t--)
    {
      ans=0;
    scanf("%s",a+1);n=strlen(a+1);
    scanf("%s",b+1);m=strlen(b+1);
    for(int d1=0;d1<=n;d1++)
      for(int d2=0;d2<=m;d2++)
        for(int i=1,j=d1;j<=n;i++,j++)
          for(int k=1,l=d2;l<=m;k++,l++)
          {
              if(d1+d2<=1) dp[i][j][k][l]=1;
              else
              {
                 dp[i][j][k][l]=0;
                 if(a[j]==a[i]&&d1>1)
                 {
                   if(dp[i+1][j-1][k][l]) dp[i][j][k][l]=1;
                 }
                 if(a[j]==b[k]&&d1&&d2)
                 {
                   if(dp[i][j-1][k+1][l]) dp[i][j][k][l]=1;
                 }
                 if(b[l]==a[i]&&d1&&d2)
                 {
                   if(dp[i+1][j][k][l-1]) dp[i][j][k][l]=1;
                 }
                 if(b[l]==b[k]&&d2>1)
                 {
                   if(dp[i][j][k+1][l-1]) dp[i][j][k][l]=1;
                 }
              }
              if(dp[i][j][k][l])ans=max(ans,d1+d2);
        }
        cout<<ans<<endl;
    }
    return 0;
}