合并回文子串

题目:

输入两个字符串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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值