[UVA][dp、最長共同回文] 12473 - Common Palindrome
A palindrome is a string that reads the same from the left as it does from the right. Given two strings A and B, you need to find the length of longest palindrome which is a subsequence of both A and B. A subsequence is a sequence obtained by deleting zero or more characters from a string.
For example, say, A = “cfcfaafc”, B = “efagfc”. Then the longest palindrome which is a subsequence of both A and B is “faf”. So the answer is 3.
Input
First line of the input contains a positive integer T(T <= 100). Each of the following T cases consists of 2 lines. These 2 lines contain the strings A and B, respectively. Length of A and B will not be more than 60. All these strings contain only lowercase letters (‘a’ -‘z’). No empty strings will appear in the input.
Output
For each case, print a line of the form Case <x>: <y>, where x is the case number and y is the length of the longest common palindromic subsequence.
Sample Input
3
cfcfaafc
efagfc
afbcdfca
bcadfcgyfka
palin
drome
Sample Output
Case 1: 3
Case 2: 5
Case 3: 0
動態規劃 dp[la][ra][lb][rb] = 最長共同回文長度
[la, ra] 區間於 A string. [lb, rb] 區間於 B string.
因此很簡單地會發現
if(A[la] == A[ra] && B[lb] == B[rb] && A[la] == B[lb])
dp[la][ra][lb][rb] = dp[la+1][ra-1][lb+1][rb-1]+2
else
dp[la][ra][lb][rb] = max(dp[la+1][ra][lb][rb], dp[la][ra-1][lb][rb], dp[la][ra][lb+1][rb], dp[la][ra][lb][rb-1]);
因此算起來是 O(n^4), 60^4 算起來可以在 10 秒內通過。
//1.800 s
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char dp[65][65][65][65];
int main() {
int t, cases = 0;
int i, j, k, p, q, r;
int a1, b1, c1, d1;
char A[105], B[105];
scanf("%d", &t);
while(t--) {
scanf("%s %s", &A, &B);
int la = strlen(A), lb = strlen(B);
memset(dp, 0, sizeof(dp));
for(i = 0; i < la; i++) {
for(j = 0; j < lb; j++) {
if(A[i] == B[j])
dp[i][i][j][j] = 1;
}
}
for(i = 0; i < la; i++) {
for(j = 0; i+j < la; j++) {
for(p = 0; p < lb; p++) {
for(q = 0; p+q < lb; q++) {
if(A[j] == A[i+j] && B[q] == B[p+q] && p && i && A[j] == B[q]) {
dp[j][i+j][q][p+q] = dp[j+1][i+j-1][q+1][p+q-1]+2;
//printf("(%d %d %d %d)%d\n", j, i+j, q, p+q, dp[j+1][i+j-1][q+1][p+q-1]);
}
if(j+1 <= i+j)
dp[j][i+j][q][p+q] = max(dp[j][i+j][q][p+q], dp[j+1][i+j][q][p+q]);
if(j <= i+j-1)
dp[j][i+j][q][p+q] = max(dp[j][i+j][q][p+q], dp[j][i+j-1][q][p+q]);
if(q+1 <= p+q)
dp[j][i+j][q][p+q] = max(dp[j][i+j][q][p+q], dp[j][i+j][q+1][p+q]);
if(q <= p+q-1)
dp[j][i+j][q][p+q] = max(dp[j][i+j][q][p+q], dp[j][i+j][q][p+q-1]);
//printf("(%d %d %d %d) dp %d\n", j, i+j, q, p+q, (int)dp[j][i+j][q][p+q]);
}
}
}
}
printf("Case %d: %d\n", ++cases, dp[0][la-1][0][lb-1]);
}
return 0;
}
/*
5
gabgcccbadacg
gabxxxbacccgbadab
Case 1: 7
3
cfcfaafc
efagfc
afbcdfca
bcadfcgyfka
palin
drome
Case 1: 3
Case 2: 5
Case 3: 0
5
a
b
*/