合并回文子串 (nowcoder.com)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
在此用f[i][j][k][l]表示从字符串a中取出第i个到第j个字符间的子串和从字符串b中取出第k个到第l个字符间的子串是否满足回文串
这里的最小的区间,无疑是边界,当出现f[i][i][k][k]的时候,即取的两个串的长度小于等于1时, 如果此时又恰好a[i]==b[k]的话, f数组取值可为1
以下任一种合理,最终f取值就为真
区间dp要从短区间扩展到长区间,所以如果不是使用记忆化搜索的话,就需要按区间长短来枚举而不是直接枚举首末端点
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 55; bool f[N][N][N][N]; char a[N], b[N]; int main() { int t; cin >> t; while(t --) { scanf("%s", a+1); scanf("%s", b+1); int la = strlen(a + 1); int lb = strlen(b + 1); int res = 0; for(int l1 = 0; l1 <= la; l1 ++) //枚举a串的长度 for(int l2 = 0; l2 <= lb; l2 ++) //枚举b串的长度 for(int i = 1; i+l1-1 <= la; i ++) for(int k = 1; k+l2-1 <= lb; k ++) { int j = i+l1-1, l = k+l2-1; if(l1+l2 <= 1) f[i][j][k][l] = 1; else{ f[i][j][k][l] = 0; if(l1 > 1) f[i][j][k][l] |= ((a[i]==a[j]) && f[i+1][j-1][k][l]); if(l2 > 1) f[i][j][k][l] |= ((b[k]==b[l]) && f[i][j][k+1][l-1]); if(l1 && l2){ f[i][j][k][l] |= ((a[i]==b[l]) && f[i+1][j][k][l-1]); f[i][j][k][l] |= ((a[j]==b[k]) && f[i][j-1][k+1][l]); } } if(f[i][j][k][l]){ res = max(res, l1+l2); } } cout << res << endl; ; } return 0; }