题意
传送门 NC 13230
题解
对于单串最长回文子串的长度,一种解法为二维
D
P
DP
DP。
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 代表字符串区间
[
i
,
j
)
[i,j)
[i,j) 的最长回文子串长度,由于单串区间长度的增加只有向左右界移动的可能;考虑到回文子串对称的字符的位置有在区间两端,或不在两端,或一个在区间内而另一个在区间端点三种可能;则有递推式
d
p
[
i
]
[
j
]
=
{
d
p
[
i
+
1
]
[
j
−
1
]
+
1
s
t
r
[
i
]
=
s
t
r
[
j
−
1
]
m
a
x
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
o
t
h
e
r
w
i
s
e
dp[i][j]=\begin{cases} dp[i+1][j-1] + 1 & str[i]=str[j-1]\\ max(dp[i+1][j], dp[i][j-1]) & otherwise\\ \end{cases}
dp[i][j]={dp[i+1][j−1]+1max(dp[i+1][j],dp[i][j−1])str[i]=str[j−1]otherwise 本题涉及
2
2
2 个字符串,求合并的回文子串长度。此时区间的增加,对于左界或右界而言都有
2
2
2 种可能,如果仍然使用子串的转移方程则需要写出
2
×
2
×
3
2\times 2 \times 3
2×2×3 个可能的状态转移。为了编程简单,改变
D
P
DP
DP 的定义,
d
p
[
x
1
]
[
y
1
]
[
x
2
]
[
y
2
]
dp[x1][y1][x2][y2]
dp[x1][y1][x2][y2] 代表两个字符串
a
,
b
a,b
a,b 分别在
[
x
1
,
y
1
)
,
[
x
2
,
y
2
)
[x1,y1),[x2,y2)
[x1,y1),[x2,y2) 的合并是否是回文串,此时需要在状态的遍历中更新答案
d
p
[
x
1
]
[
y
1
]
[
x
2
]
[
y
2
]
∣
=
{
d
p
[
x
1
+
1
]
[
y
1
]
[
x
2
]
[
y
2
−
1
]
x
1
<
y
1
&
x
2
<
y
2
&
a
[
x
1
]
=
b
[
y
2
−
1
]
d
p
[
x
1
+
1
]
[
y
1
−
1
]
[
x
2
]
[
y
2
]
x
1
+
1
<
y
1
&
x
2
<
=
y
2
&
a
[
x
1
]
=
a
[
y
1
−
1
]
d
p
[
x
1
]
[
y
1
−
1
]
[
x
2
+
1
]
[
y
2
]
x
1
<
y
1
&
x
2
<
y
2
&
a
[
y
1
−
1
]
=
b
[
x
2
]
d
p
[
x
1
]
[
y
1
]
[
x
2
+
1
]
[
y
2
−
1
]
x
1
<
=
y
1
&
x
2
+
1
<
y
2
&
b
[
x
2
]
=
b
[
y
2
−
1
]
dp[x1][y1][x2][y2]\ |=\begin{cases} dp[x1 + 1][y1][x2][y2 - 1] & x1 < y1 \& x2 < y2\&a[x1] = b[y2 - 1] \\ dp[x1 + 1][y1 - 1][x2][y2] & x1 + 1 < y1 \& x2 <= y2 \& a[x1] = a[y1 - 1] \\ dp[x1][y1 - 1][x2 + 1][y2] & x1 < y1 \& x2 < y2 \& a[y1 - 1] = b[x2] \\ dp[x1][y1][x2 + 1][y2 - 1] & x1 <= y1 \& x2 + 1 < y2 \& b[x2] = b[y2 - 1] \\ \end{cases}
dp[x1][y1][x2][y2] ∣=⎩⎪⎪⎪⎨⎪⎪⎪⎧dp[x1+1][y1][x2][y2−1]dp[x1+1][y1−1][x2][y2]dp[x1][y1−1][x2+1][y2]dp[x1][y1][x2+1][y2−1]x1<y1&x2<y2&a[x1]=b[y2−1]x1+1<y1&x2<=y2&a[x1]=a[y1−1]x1<y1&x2<y2&a[y1−1]=b[x2]x1<=y1&x2+1<y2&b[x2]=b[y2−1]
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 55
bool dp[maxn][maxn][maxn][maxn];
char a[maxn], b[maxn];
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf(" %s%s", a, b);
memset(dp, 0, sizeof(dp));
int n1 = strlen(a), n2 = strlen(b), res = 0;
for (int w1 = 0; w1 <= n1; w1++)
{
for (int x1 = 0; x1 + w1 <= n1; x1++)
{
for (int w2 = 0; w2 <= n2; w2++)
{
for (int x2 = 0; x2 + w2 <= n2; x2++)
{
int y1 = x1 + w1, y2 = x2 + w2, len = w1 + w2, f = 0;
if (w1 + w2 <= 1)
{
f = 1;
}
if (x1 < y1 && x2 < y2 && a[x1] == b[y2 - 1])
{
f |= dp[x1 + 1][y1][x2][y2 - 1];
}
if (x1 + 1 < y1 && x2 <= y2 && a[x1] == a[y1 - 1])
{
f |= dp[x1 + 1][y1 - 1][x2][y2];
}
if (x1 < y1 && x2 < y2 && a[y1 - 1] == b[x2])
{
f |= dp[x1][y1 - 1][x2 + 1][y2];
}
if (x1 <= y1 && x2 + 1 < y2 && b[x2] == b[y2 - 1])
{
f |= dp[x1][y1][x2 + 1][y2 - 1];
}
if (f)
{
dp[x1][y1][x2][y2] = f;
res = max(res, len);
}
}
}
}
}
printf("%d\n", res);
}
return 0;
}