24h購物| | PChome| 登入
2013-05-05 15:43:10| 人氣667| 回應0 | 上一篇 | 下一篇

[UVA][dp、最長共同回文][faster] 12473 - Common Palindrome

推薦 0 收藏 0 轉貼0 訂閱站台

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



原本的方程推導 http://mypaper.pchome.com.tw/zerojudge/post/1324334213
從 220 ms 再加速 http://acm.hust.edu.cn/vjudge/contest/viewSource.action?id=477042

想法是這樣的,窮舉下一個匹配到的字符,然後進行 dp。
例如 [a ,,, a][a ,,, a] 是上次的, 窮舉 'a'-'z', 假使是 'e'
[a ... e ,,, e ... a][a ... e ,,, e ... a]
其中窮舉出來的字符間距離越大越好。


// 0.072 s
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxL (17000000>>5)+1
#define GET(x) (mark[(x)>>5]>>((x)&31)&1)
#define SET(x) (mark[(x)>>5] |= 1<<((x)&31))
using namespace std;
int dp[65][65][65][65];
int appA[65][65], appB[65][65];
int mark[maxL];
char A[105], B[105];
int LA, LB;
int mapped[1008];
int dfs(int la, int ra, int lb, int rb) {
    if(la > ra || lb > rb)  return 0;
    if(GET((la<<18)|(ra<<12)|(lb<<6)|(rb)))
        return dp[la][ra][lb][rb];
    SET((la<<18)|(ra<<12)|(lb<<6)|(rb));
    int &ret = dp[la][ra][lb][rb];
    int sla, sra, slb, srb;
    int com = appA[la][ra]&appB[lb][rb], i;
    ret = 0;
    //for(int i = 'a'; i <= 'z'; i++) {
    while(com) {
        i = mapped[(com&(-com))%1007]+'a';
        com ^= com&(-com);
        sla = la;
        while(sla <= ra && A[sla] != i)     sla++;
        if(sla > ra)    continue;
        sra = ra;
        while(sra >= sla && A[sra] != i)    sra--;
        if(sra < sla)    continue;
        slb = lb;
        while(slb <= rb && B[slb] != i)     slb++;
        if(slb > rb)    continue;
        srb = rb;
        while(srb >= slb && B[srb] != i)    srb--;
        if(srb < slb)    continue;
        if(sla == sra || slb == srb)
            ret = max(ret, 1);
        else
            ret = max(ret, dfs(sla+1, sra-1, slb+1, srb-1)+2);
    }
    return ret;
}
int main() {
    for(int i = 0; i < 26; i++) {
        if(mapped[(1<<i)%1007])
            puts("error");
        mapped[(1<<i)%1007] = i;
    }
    int t, cases = 0;
    scanf("%d", &t);
    while(t--) {
        scanf("%s %s", &A, &B);
        LA = strlen(A), LB = strlen(B);
        memset(mark, 0, sizeof(mark));
        int usedA[128] = {}, usedB[128] = {};
        int i, j;
        for(i = 0; i < LA; i++)
            usedA[A[i]-'a'] = 1;
        for(i = 0; i < LB; i++)
            usedB[B[i]-'a'] = 1;
        for(i = 0, j = 0; i < LA; i++)
            if(usedB[A[i]-'a'])
                A[j++] = A[i];
        A[j] = '\0';
        for(i = 0, j = 0; i < LB; i++)
            if(usedA[B[i]-'a'])
                B[j++] = B[i];
        B[j] = '\0';
        LA = strlen(A);
        LB = strlen(B);
        if(LA == 0 || LB == 0) {
            printf("Case %d: 0\n", ++cases);
            continue;
        }
        for(i = 0; i < LA; i++) {
            appA[i][i] = 1<<(A[i]-'a');
            for(j = i+1; j < LA; j++) {
                appA[i][j] = appA[i][j-1]|(1<<(A[j]-'a'));
            }
        }
        for(i = 0; i < LB; i++) {
            appB[i][i] = 1<<(B[i]-'a');
            for(j = i+1; j < LB; j++) {
                appB[i][j] = appB[i][j-1]|(1<<(B[j]-'a'));
            }
        }
        printf("Case %d: %d\n", ++cases, dfs(0, LA-1, 0, LB-1));
    }
    return 0;
}
/*
100
gabgcccbadacg
gabxxxbacccgbadab
cfcfaafc
efagfc
afbcdfca
bcadfcgyfka
palin
drome
*/

台長: Morris
人氣(667) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 不分類 | 個人分類: UVA |
此分類下一篇:[UVA][線段樹] 1232 - SKYLINE
此分類上一篇:[UVA][字串處理] 726 - Decode

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文