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;
}
/*样例区
*/
//------------------------------------------------------------
标签:子串,1026,int,l2,&&,l1,DP,回文 来源: https://www.cnblogs.com/er007/p/16462624.html