1. 程式人生 > >light oj 1025 - The Specials Menu(區間DP->求刪除字元使其成為迴文串的方法數)

light oj 1025 - The Specials Menu(區間DP->求刪除字元使其成為迴文串的方法數)


1025 - The Specials Menu
    PDF (English) Statistics Forum
Time Limit: 2 second(s) Memory Limit: 32 MB

Feuzem is an unemployed computer scientist who spends his days working at odd-jobs. While on the job he always manages to find algorithmic problems within mundane aspects of everyday life.

Today, while writing down the specials menu at the restaurant he's working at, he felt irritated by the lack of palindromes (strings which stay the same when reversed) on the menu. Feuzem is a big fan of palindromic problems, and started thinking about the number of ways he could remove letters from a particular word so that it would become a palindrome.

Two ways that differ due to order of removing letters are considered the same. And it can also be the case that no letters have to be removed to form a palindrome.

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case contains a single word W (1 ≤ length(W) ≤ 60)

.

Output

For each case, print the case number and the total number of ways to remove letters from W such that it becomes a palindrome.

Sample Input

Output for Sample Input

3

SALADS

PASTA

YUMMY

Case 1: 15

Case 2: 8

Case 3: 11



注意不刪除如果是字串也是一種方法;

題目大意:一串字元, 通過刪除其中一些字元, 能夠使這串字元變成迴文串。 現在給你一串字元,問能夠得到多少種不同的迴文串;

注意:字串"abba", 可以得到9串迴文串,分別為'a', 'a', 'b', 'b', 'aa', 'bb', 'aba', 'aba', 'abba'.

解題思路:宣告dp[i][j]為字串[i,j]區間中通過刪除可以得到不同迴文串的數量

那麼有以下兩種情況:

1:當str[i] != str[j]時, dp[i][j] = dp[i][j-1] + dp[i+1][j] - dp[i+1][j-1]; (之所以減去dp[i+1][j-1] 是前面兩項多加了一個dp[i+1][j-1])

2:當str[i] == str[j]時, dp[i][j] = (dp[i][j-1] + dp[i+1][j] - dp[i+1][j-1]) + (dp[i+1][j-1] + 1);(前面一項是指str[i]和str[j]不對應時能夠組成迴文串的方案數,第二項是指str[i]和str[j]對應時能夠組成迴文串的方案數)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 100;
long long  dp[N][N];
char str[N];


int main()
{
    int t, ncase=1;
    scanf("%d", &t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%s",str);
        int len=strlen(str);
        for(int i=0; i<len; i++)
            dp[i][i]=1;
        for(int l=1; l<len; l++)
        {
            for(int i=0; i<len-l; i++)
            {
                int j=i+l;
                if(str[i]!=str[j])
                    dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1];
                else
                    dp[i][j]=dp[i][j-1]+dp[i+1][j]+1;中間的方法數加上倆邊不刪除中間的方法數加上,中間刪除倆邊不刪;
            }
        }
        printf("Case %d: %lld\n",ncase++,dp[0][len-1]);
    }
    return 0;
}