uva_10069_Distinct Subsequences (普通DP)

这题是一个普通的dp,lcs变形,这里需要注意的是初始化,和这里需要使用高精度
阶段:以主串的字符顺序作为阶段,从后面枚举
状态:dp[i][j] 表示主串的第i个字符和子串的第j个字符匹配的方案数
                    dp[i][j+1] (stra[i] != strb[j])
状态转移:dp[i][j] -> 
                    dp[i][j+1]+dp[i+1][j+1] (stra[i] == strb[j])
ans = dp[0][0];
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXLEN_A        105
#define MAXLEN_B        10005
#define MAXSIZE         128

char dp[MAXLEN_A][MAXLEN_B][MAXSIZE], stra[MAXLEN_A], strb[MAXLEN_B];

void add(int a_r, int a_c, int b_r, int b_c, int rst_r, int rst_c)
{
        int bit(0), tmp;
        for(int i = MAXSIZE-1; i >= 0; i --) {
                tmp = bit+dp[a_r][a_c][i]-'0'+dp[b_r][b_c][i]-'0';
                dp[rst_r][rst_c][i] = tmp%10+'0'; bit = tmp/10;
        }
}

int dynamic_programming(void)
{
        int lena(strlen(stra)), lenb(strlen(strb));
        for(int i = 0; i <= lena; i ++) {
                for(int j = 0; j <= lenb; j ++) {
                        for(int k = 0; k < MAXSIZE; k ++) {
                                dp[i][j][k] = '0';
                        }
                }
        }
        for(int i = 0; i < MAXSIZE; i ++) {
                dp[MAXLEN_A-1][MAXLEN_B-1][i] = '0';
        }
        for(int i = 0; i < lenb; i ++) {
                dp[lena][i][MAXSIZE-1] = '1';
        }
        dp[lena][lenb][MAXSIZE-1] = (stra[lena-1] == strb[lenb-1])? '1' : '0';

        for(int j = lenb-1; j >= 0; j -- ) {
                for(int i = lena-1; i >= 0; i --) {
                        if( stra[i] == strb[j] ) {
                                add(i, j+1, i+1, j+1, i, j); continue;
                        }
                        add(i, j+1, MAXLEN_A-1, MAXLEN_B-1, i, j);                        
                }
        }
}

void output(const int &r, const int &c)
{
        int idx(0);
        for( ; idx < MAXSIZE && '0' == dp[r][c][idx]; idx ++) {}
        if( idx == MAXSIZE ) {
                printf("0\n"); return;
        }
        for( ; idx < MAXSIZE; idx ++) {
                printf("%c", dp[r][c][idx]);
        }
        printf("\n");
}

int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int cas;
        scanf("%d", &cas);
        for(; cas; cas --) {
                scanf("%s %s", strb, stra);
                dynamic_programming(); output(0, 0);
        }
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值