题目:
输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变。如"abc"和"xyz"可以被组合成"axbycz"或"abxcyz"等。
我们定义字符串的价值为其最长回文子串的长度(回文串表示从正反两边看完全一致的字符串,如"aba"和"xyyx")。
需要求出所有可能的C中价值最大的字符串,输出这个最大价值即可
输入描述:
第一行一个整数T(T ≤ 50)。
接下来2T行,每两行两个字符串分别代表A,B(|A|,|B| ≤ 50),A,B的字符集为全体小写字母。
输出描述:
对于每组数据输出一行一个整数表示价值最大的C的价值。
示例1
输入
2
aa
bb
a
aaaabcaa
输出
4
5
解析:
单独考虑合成的回文串,我们可以知道这个回文串一定是由字符串A,字符串B合成的,并且来自字符串A的字符相对位置没有变化,来自字符串B的字符的相对位置也没有变化。假设A【i】【j】为字符串A(be1<=i<=en1),B【k】【l】为字符串B;两个字符串合并的长度为j-i+1+l-k+1;
考虑动态规划的状态 f[i][j][k][l]表示 a[i, j]与 b[k, l]的 combine 能否组成回文子串。 则可以匹配第一个字符和最后一个字符来转移,根据第一个字符和最后一个字符分别来自 a 还是 b 共有四种转移:
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
using namespace std;
typedef pair<int,int>P;
const int MAXN=100010;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
bool dp[55][55][55][55];//dp[i][j][k][l]表示是构成回文;
char a[55],b[55];
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%s %s", a+1, b+1);
int asz = strlen(a+1);
int bsz = strlen(b+1);
int ans = 1;
for(int l1 = 0; l1 <= asz; ++l1)//枚举字符串A的长度
{
for(int l2 = 0; l2 <= bsz; l2++)//枚举字符串b的长度
{
//i,j,k,l分别为两个子串的起点和终点;
for(int i = 1, j = l1+i-1; j <= asz; ++j, ++i )
{
for(int k = 1, l = l2+k-1; l <= bsz; l++, k++)
{
if(l1+l2 <= 1) dp[i][j][k][l] = 1;//当长度为1时是一个回文串
else
{
dp[i][j][k][l]=0;
if(l1>1&&a[i]==a[j])dp[i][j][k][l]|=dp[i+1][j-1][k][l];
if(l2>1&&b[k]==b[l])dp[i][j][k][l]|=dp[i][j][k+1][l-1];
if(l1&&l2&&a[i]==b[l])dp[i][j][k][l]|=dp[i+1][j][k][l-1];
if(l1&&l2&&a[j]==b[k])dp[i][j][k][l]|=dp[i][j-1][k+1][l];
}
if(dp[i][j][k][l])
{
ans = max(ans, j-i+1+l-k+1);
}
}
}
}
}
cout<<ans<<endl;
}
return 0;
}