uva_10069_Distinct Subsequences (普通DP)

本文探讨了一种基于动态规划和最长公共子序列(LCS)变形的算法,特别关注了高精度计算的需求。通过阶段划分和状态定义,实现了一种高效的解决方案,适用于字符串匹配场景。
这题是一个普通的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;
}

在数据库查询中,`APPROX_COUNT_DISTINCT()` 和 `DISTINCT` 是用于处理唯一值的两种不同机制,它们的设计目标和使用场景有显著差异。 `APPROX_COUNT_DISTINCT()` 是一种近似计数方法,它通过牺牲一定的准确性来换取更高的性能和更低的资源消耗。该函数通常使用概率算法(如 HyperLogLog)来估算唯一值的数量。由于其近似性质,它适用于对结果精度要求不苛刻、但对查询速度和资源效率要求较高的场景。例如,在大数据集上进行快速分析,或者在实时仪表板中提供趋势概览时[^1]。 与之相对,`DISTINCT` 是一种精确计数方法,它会返回查询结果中所有唯一的值,且结果是准确无误的。`DISTINCT` 通常用于需要精确唯一值数量的场景,例如统计用户注册数量、计算唯一访问者数量等。然而,由于其需要对数据进行完全去重,因此在大数据集上使用时可能会导致较高的计算成本和较长的查询时间[^1]。 从性能角度来看,`APPROX_COUNT_DISTINCT()` 通常比 `DISTINCT` 更快,尤其是在处理大规模数据集时。这是因为 `APPROX_COUNT_DISTINCT()` 不需要存储或处理所有数据点,而是通过算法估算唯一值的数量。而 `DISTINCT` 需要遍历所有记录并存储唯一值,这在数据量大时会导致显著的性能下降[^1]。 在资源消耗方面,`APPROX_COUNT_DISTINCT()` 通常占用更少的内存和计算资源,因为它不需要保存所有唯一值的完整列表。相反,`DISTINCT` 操作可能需要大量的内存来存储中间结果,特别是在数据集中存在大量唯一值的情况下[^1]。 使用场景上,`APPROX_COUNT_DISTINCT()` 更适合于需要快速响应和容忍一定误差的数据分析任务,如市场趋势分析、用户行为模式识别等。而 `DISTINCT` 更适合于需要精确结果的业务逻辑,如财务报表中的唯一客户计数、库存管理系统中的唯一产品编号统计等[^1]。 ### 示例代码 对于 `APPROX_COUNT_DISTINCT()` 的使用,假设有一个用户访问日志表 `user_visits`,可以通过以下 SQL 查询来获取近似的独立访问者数量: ```sql SELECT APPROX_COUNT_DISTINCT(user_id) AS approx_unique_visitors FROM user_visits; ``` 而对于 `DISTINCT`,同样假设有一个用户注册表 `user_registrations`,可以通过以下 SQL 查询来获取精确的注册用户数量: ```sql SELECT COUNT(DISTINCT user_id) AS exact_unique_users FROM user_registrations; ``` ### 总结 选择 `APPROX_COUNT_DISTINCT()` 还是 `DISTINCT` 取决于具体的应用需求。如果对结果的精确度要求不高,且追求更高的性能和更低的资源消耗,则可以选择 `APPROX_COUNT_DISTINCT()`;如果需要得到确切的唯一值数量,则应使用 `DISTINCT`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值