1026 合并回文子串 区间DP

链接:https://ac.nowcoder.com/acm/problem/13230
来源:牛客网

题目描述

输入两个字符串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

分析

合并回文子串,要求的是连续的子串是回文的,对于回文串,其实可以从小区间看到大区间,如果更小的一段区间是回文串,且最外面的两个数相等,那这个更大的区间也是回文子串

如果只有一个序列,写两层for循环的区间DP就可以了,由于有两个序列,序列的每个子序列都有可能,所以要四层for循环

状态方程:f[i][j][l][r] :表示第一个序列的区间[i,j] 第二个区间的[l][r] 是不是回文子串

状态转移方程式:f[i][j][l][r] |= f[i+1][j-1][l][r] (a[i] == a[j] ) 

//-------------------------代码----------------------------

//#define int LL
const int N = 60;
int n,m;
int f[N][N][N][N];
char a[N],b[N];

void solve()
{
cin>>a+1>>b+1;
int ans = 0;
int n = strlen(a+1);
int m = strlen(b+1);
for(int l1 = 0;l1<=n;l1 ++ ) {
for(int l2 = 0;l2<=m;l2++ ) {
for(int i = 1;i<=n - l1 + 1;i ++ ) {
for(int l = 1;l<= m - l2 + 1;l ++ ) {
int j = i + l1 - 1,r = l + l2 - 1;
if(l1 + l2 <= 1) f[i][j][l][r] = 1;
else {
f[i][j][l][r] = 0;
if(a[i] == a[j] && l1 >= 2) {
if(f[i+1][j-1][l][r]) f[i][j][l][r] = 1;
}
if(a[i] == b[r] && l1 && l2) {
if(f[i+1][j][l][r-1]) f[i][j][l][r] = 1;
}
if(b[l] == b[r] && l2 >= 2) {
if(f[i][j][l+1][r-1]) f[i][j][l][r] = 1;
}
if(b[l] == a[j] && l1 && l2) {
if(f[i][j-1][l+1][r]) f[i][j][l][r] = 1;
}
}
if(f[i][j][l][r]) ans = max(ans,l1 + l2);
}
}
}
}
cout<<ans<<endl;
}

signed main(){
clapping();TLE;

int t;cin>>t;while(t -- )
solve();
// {solve(); }
return 0;
}

/*样例区


*/

//------------------------------------------------------------

posted @ 2022-07-10 09:47  er007  阅读(49)  评论(0编辑  收藏  举报