この記事では、最初に次のことを述べます。最も長い回文の文字列長を解決するための動的プログラミング
f [i] [j]:s [i]からs [j]で表される部分文字列が回文列であるかどうかを示し、1は0です。s
[i]とs [j]が等しいかどうかに応じてパーティション
1.s [i] == s [j]、s [i + 1]からs [j-1]が回文サブストリングである限り、s [i]からs [j]は回文サブストリングでなければなりません。s [i + 1]からs [j-1]が回文サブストリングでない場合、s [i]からs [j]も回文サブストリングであってはなりません。
2.s [i]!= S [j]次に、s [i]からs [j]は回文の部分文字列であってはなりません
状態方程式:
この質問に戻ります。この質問は2つの文字列だからです。2Dを4Dに拡張します
f [sa] [ea] [sb] [eb]:回文サブストリングを構成できるsa〜eaおよびb sb〜ebの最大長を示します
伝達方程式:
if(a[sa]==a[ea]) f[sa][ea][sb][eb]|=f[sa+1][ea-1][sb][eb];
if(b[sb]==b[eb]) f[sa][ea][sb][eb]|=f[sa][ea][sb+1][eb-1];
if(a[sa]==b[eb]) f[sa][ea][sb][eb]|=f[sa+1][ea][sb][eb-1];
if(a[ea]==b[sb]) f[sa][ea][sb][eb]|=f[sa][ea-1][sb+1][eb];
#include<bits/stdc++.h>
using namespace std;
const int N=55;
int f[N][N][N][N];
int t;
char a[N],b[N];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%s %s",(a+1),(b+1));
int ans=-1;
int lena=strlen(a+1);
int lenb=strlen(b+1);
for(int la=0;la<=lena;la++) //枚举a串的长度
for(int lb=0;lb<=lenb;lb++)//枚举b串的长度
{
for(int sa=1;sa+la-1<=lena;sa++) //枚举a串起点
{
for(int sb=1;sb+lb-1<=lenb;sb++)//枚举b串起点
{
int ea=sa+la-1;int eb=sb+lb-1;//a,b串终点
if(la+lb<=1) f[sa][ea][sb][eb]=1;//长度为1的串,初始化为1
else
{
f[sa][ea][sb][eb]=0;
if(a[sa]==a[ea]) f[sa][ea][sb][eb]|=f[sa+1][ea-1][sb][eb];
if(b[sb]==b[eb]) f[sa][ea][sb][eb]|=f[sa][ea][sb+1][eb-1];
if(a[sa]==b[eb]) f[sa][ea][sb][eb]|=f[sa+1][ea][sb][eb-1];
if(a[ea]==b[sb]) f[sa][ea][sb][eb]|=f[sa][ea-1][sb+1][eb];
}
//1表示是回文串,所以取长度la+lb
if(f[sa][ea][sb][eb]) ans=max(ans,la+lb);
}
}
}
cout<<ans<<endl;
}
}