合并回文子串
合并回文子串
https://ac.nowcoder.com/acm/problem/13230
题目描述:
输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变。如"abc"和"xyz"可以被组合成"axbycz"或"abxcyz"等。 我们定义字符串的价值为其最长回文子串的长度(回文串表示从正反两边看完全一致的字符串,如"aba"和"xyyx")。需要求出所有可能的C中价值最大的字符串,输出这个最大价值即可
题解
首先考虑单独字符串如何判断子区间是否为回文,容易知道两维dp即可维护。
简易代码: dp[i][j] = (a[i] == a[j]) ? dp[i + 1][j - 1]:0
那么回到本题,我们可以增加dp的维度便可以模仿上述转移。代码如下:if(a[i]==a[j]) dp[i][j][k][l] |= dp[i+1][j-1][k][l];
if(a[i]==b[l]) dp[i][j][k][l] |= dp[i+1][j][k][l-1];
if(b[k]==b[l]) dp[i][j][k][l] |= dp[i][j][k+1][l-1];
if(b[k]==a[j]) dp[i][j][k][l] |= dp[i][j-1][k+1][l];
dp[i][j][k][l]表示a数组的i-j区间和b数组的k-l区间是否能够构成回文数组。 最后特判一下恒成立的区间即可。
代码
#include <bits/stdc++.h> using namespace std; const int N = 55; char a[N], b[N]; bool f[N][N][N][N]; int T; int main() { cin >> T; while(T --) { cin >> (a + 1) >> (b + 1); //memset(f, 0, sizeof f); int ans = 1; for (int la = 0; la <= strlen(a+1); la ++) for (int lb = 0; lb <= strlen(b+1); lb ++) for (int l1 = 1; l1 + la - 1 <= strlen(a+1); l1 ++) for (int l2 = 1; l2 + lb - 1 <= strlen(b+1); l2 ++) { int r1 = l1 + la - 1, r2 = l2 + lb - 1; if(la + lb <= 1) f[l1][r1][l2][r2] = 1; else { f[l1][r1][l2][r2] = 0; //cout << " " <<l1 <<" " <<r1<<" " << l2 << " " << r2 << endl; //cout << f[l1][r1][l2][r2] << endl; if(a[l1]==a[r1]) f[l1][r1][l2][r2] |= f[l1 + 1][r1 - 1][l2][r2]; if(b[l2]==b[r2]) f[l1][r1][l2][r2] |= f[l1][r1][l2 + 1][r2 - 1]; if(a[l1]==b[r2]) f[l1][r1][l2][r2] |= f[l1 + 1][r1][l2][r2 - 1]; if(b[l2]==a[r1]) f[l1][r1][l2][r2] |= f[l1][r1 - 1][l2 + 1][r2]; } //cout << f[l1][r1][l2][r2] << endl; if(f[l1][r1][l2][r2]) ans = max(ans, la + lb); } cout << ans << endl; } }