(区间dp) hdu 4632 Palindrome subsequence

题目
hdu4632

题意:
输出字符串中所有子序列回文串(可以不连续)的个数。
as:aaa的所有子序列回文串是a(0),a(1),a(2),a(0)a(1),a(1)a(2),a(0)a(2),a(0)a(1)a(2) (括号里面的数字是这个字符在字符串中的坐标)

思路:
在区间i ~ j 中,

如果a [ i ] != a [ j ],dp [ i ] [ j ] = dp [ i + 1 ] [ j ] + dp [ i ][ j - 1 ] - dp [ i + 1] [ j - 1]

as:在字符串aaab中,(相同的用粗体表示)
dp [ i ] [ j - 1 ] = 7 【a(0),a(1),a(2),a(0)a(1),a(1)a(2),a(0)a(2),a(0)a(1)a(2)】
dp [ i + 1 ] [ j ] = 3 【a(1),a(2),a(1)a(2)
dp [ i + 1] [ j - 1] = 3 【a(1),a(2),a(1)a(2)
dp [ i ] [ j ] = 7 + 3 - 3 = 7

如果a [ i ] = a [ j ],dp [ i ] [ j ] = dp [ i + 1 ] [ j ] + dp [ i ][ j - 1 ] - dp [ i + 1] [ j - 1] + 1 + dp [ i + 1] [ j - 1] => dp [ i + 1 ] [ j ] + dp [ i ][ j - 1 ] + 1

as:在字符串aaaa中,(相同的用粗体表示)
dp [ i ] [ j - 1 ] = 7 【a(0),a(1)a(2),a(0)a(1),a(1)a(2),a(0)a(2),a(0)a(1)a(2)】
dp [ i + 1 ] [ j ] = 7 【a(1)a(2),a(3), a(1)a(2),a(2)a(3),a(1)a(3),a(1)a(2)a(3)】
dp [ i + 1] [ j - 1] = 3 【a(1),a(2),a(1)a(2)
1:【a(0)a(3)】
另一个dp [ i + 1] [ j - 1] = 3 【a(0)a(1)a(3),a(0)a(2)a(3),a(0)a(1)a(2)a(3)】
dp [ i ] [ j ] = 7 + 7 - 3 + 3 + 1 => 7 + 7 + 1

解法1:

#include <iostream>
#include <cstring>
#define DEBUG freopen("_in.txt", "r", stdin); freopen("_out1.txt", "w", stdout);
#define CASEE int t; cin >> t; for (int ti = 1; ti <= t; ti++)
using namespace std;
const int MAXN = 1010;
const int MOD = 10007;
char s[MAXN];
int dp[MAXN][MAXN];
void solve(){
    
    
    scanf(" %s", s);
    int lena = strlen(s);
    for (int i = 0; i < lena; i++)
        dp[i][i] = 1;
    for (int len = 1; len < lena; len++)
        for (int i = 0; i < lena - len; i++){
    
    
            int j = i + len;
            if (s[i] == s[j])
                dp[i][j] = dp[i+1][j] + dp[i][j-1] + 1;
            else
                dp[i][j] = dp[i+1][j] - dp[i+1][j-1] + dp[i][j-1];
            dp[i][j] = (dp[i][j] + MOD) % MOD;  //有可能是负数(有减法)所有要+MOD
        }
    printf("%d\n", dp[0][lena-1]);
}
int main(){
    
    
    CASEE{
    
    
        printf("Case %d: ", ti);
        solve(); 
    }
    return 0;
}

解法2:

#include <iostream>
#include <cstring>
#define DEBUG freopen("_in.txt", "r", stdin); freopen("_out1.txt", "w", stdout);
#define CASEE int t; cin >> t; for (int ti = 1; ti <= t; ti++)
using namespace std;
const int MAXN = 1010;
const int MOD = 10007;
char s[MAXN];
int dp[MAXN][MAXN];
void solve(){
    
    
    scanf(" %s", s);
    int lena = strlen(s);
    for (int i = 0; i < lena; i++)
        dp[i][i] = 1;
    for (int i = lena - 1; i >= 0; i--)
        for (int j = i + 1; j < lena; j++){
    
    
            if (s[i] == s[j])
                dp[i][j] = dp[i+1][j] + dp[i][j-1] + 1;
            else
                dp[i][j] = dp[i+1][j] - dp[i+1][j-1] + dp[i][j-1];
            dp[i][j] = (dp[i][j] + MOD) % MOD;  //有可能是负数(有减法)所有要+MOD
        }
    printf("%d\n", dp[0][lena-1]);
}
int main(){
    
    
    CASEE{
    
    
        printf("Case %d: ", ti);
        solve(); 
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ymxyld/article/details/113787691