【动态规划】【子序列除重】【C++算法】1987不同的好子序列数目

简介: 【动态规划】【子序列除重】【C++算法】1987不同的好子序列数目

作者推荐

【动态规划】【状态压缩】【2次选择】【广度搜索】1494. 并行课程 II

本文涉及知识点

动态规划汇总

LeetCode1987:不同的好子序列数目

给你一个二进制字符串 binary 。 binary 的一个 子序列 如果是 非空 的且没有 前导 0 (除非数字是 “0” 本身),那么它就是一个 好 的子序列。

请你找到 binary 不同好子序列 的数目。

比方说,如果 binary = “001” ,那么所有 好 子序列为 [“0”, “0”, “1”] ,所以 不同 的好子序列为 “0” 和 “1” 。 注意,子序列 “00” ,“01” 和 “001” 不是好的,因为它们有前导 0 。

请你返回 binary 中 不同好子序列 的数目。由于答案可能很大,请将它对 109 + 7 取余 后返回。

一个 子序列 指的是从原数组中删除若干个(可以一个也不删除)元素后,不改变剩余元素顺序得到的序列。

示例 1:

输入:binary = “001”

输出:2

解释:好的二进制子序列为 [“0”, “0”, “1”] 。

不同的好子序列为 “0” 和 “1” 。

示例 2:

输入:binary = “11”

输出:2

解释:好的二进制子序列为 [“1”, “1”, “11”] 。

不同的好子序列为 “1” 和 “11” 。

示例 3:

输入:binary = “101”

输出:5

解释:好的二进制子序列为 [“1”, “0”, “1”, “10”, “11”, “101”] 。

不同的好子序列为 “0” ,“1” ,“10” ,“11” 和 “101” 。

提示:

1 <= binary.length <= 105

binary 只含有 ‘0’ 和 ‘1’ 。

动态规划

除0外,不存在以0开始的子序列。如果存在0,则必定存在子序列{0}。以下的分析排除{0}。

排除{0}后任意合法子序列在后面增加0或1,都是合法子序列。

动态规划的状态表示

pre[0] 从binary[0,i)中选择若干字符,形成以0结束的合法子序列数量。pre[1]以1结束的子序列数量。

dp和pre类似,对应的是binary[0,i+1)。

动态规划的转移方程

binary[i]为1

{ p r e [ 0 ] 不选择当前字符,以 0 结束的字符数量 情况一 p r e [ 1 ] 不选择当前字符,以 1 结束的字符数 情况二 p r e [ 0 ] + p r e [ 1 ] + 1 选择当前字符,以 1 结束的字符数量。 情况三 \begin{cases} pre[0] & 不选择当前字符,以0结束的字符数量 & 情况一 \\ pre[1] & 不选择当前字符,以1结束的字符数 & 情况二 \\ pre[0]+pre[1]+1 & 选择当前字符,以1结束的字符数量。 & 情况三 \\ \end{cases}pre[0]pre[1]pre[0]+pre[1]+1不选择当前字符,以0结束的字符数量不选择当前字符,以1结束的字符数选择当前字符,以1结束的字符数量。情况一情况二情况三

情况三又可以分三种情况:

{ p r e [ 0 ] 倒数第二个字符是 0 情况三一 p r e [ 1 ] 倒数第二个字符是 1 情况三二 1 子序列 1 。 情况三三 \begin{cases} pre[0] & 倒数第二个字符是0 & 情况三一 \\ pre[1] & 倒数第二个字符是1 & 情况三二 \\ 1 & 子序列{1}。 & 情况三三 \\ \end{cases}pre[0]pre[1]1倒数第二个字符是0倒数第二个字符是1子序列1情况三一情况三二情况三三

情况一、情况二、情况三 内部不存在重复情况。

情况一以0结尾,情况二、三以1结尾,所以情况一和情况二(三)不会重复。

情况二所有的情况都和情况三重合,情况二分类:

{ 倒数第二个字符是 0 被情况三一包含 倒数第二个字符是 1 被情况三二包含 子序列 1 。 和情况三三重复 \begin{cases} 倒数第二个字符是0 & 被情况三一包含 \\ 倒数第二个字符是1 & 被情况三二包含 \\ 子序列{1}。 & 和情况三三 重复\\ \end{cases}倒数第二个字符是0倒数第二个字符是1子序列1被情况三一包含被情况三二包含和情况三三重复

总结

dp[1] = pre[0]+pre[1]+1

dp[0] = pre[0]

binary[i]为0

不能为子序列{0}

dp[0] = pre[0]+pre[1]

dp[1] = pre[1]

动态规划的初始值

pre 全为0。

动态规划的返回值

pre之和。

代码

template<int MOD = 1000000007>
class C1097Int
{
public:
  C1097Int(long long llData = 0) :m_iData(llData% MOD)
  {
  }
  C1097Int  operator+(const C1097Int& o)const
  {
    return C1097Int(((long long)m_iData + o.m_iData) % MOD);
  }
  C1097Int& operator+=(const C1097Int& o)
  {
    m_iData = ((long long)m_iData + o.m_iData) % MOD;
    return *this;
  }
  C1097Int& operator-=(const C1097Int& o)
  {
    m_iData = (m_iData + MOD - o.m_iData) % MOD;
    return *this;
  }
  C1097Int  operator-(const C1097Int& o)
  {
    return C1097Int((m_iData + MOD - o.m_iData) % MOD);
  }
  C1097Int  operator*(const C1097Int& o)const
  {
    return((long long)m_iData * o.m_iData) % MOD;
  }
  C1097Int& operator*=(const C1097Int& o)
  {
    m_iData = ((long long)m_iData * o.m_iData) % MOD;
    return *this;
  }
  bool operator<(const C1097Int& o)const
  {
    return m_iData < o.m_iData;
  }
  C1097Int pow(long long n)const
  {
    C1097Int iRet = 1, iCur = *this;
    while (n)
    {
      if (n & 1)
      {
        iRet *= iCur;
      }
      iCur *= iCur;
      n >>= 1;
    }
    return iRet;
  }
  C1097Int PowNegative1()const
  {
    return pow(MOD - 2);
  }
  int ToInt()const
  {
    return m_iData;
  }
private:
  int m_iData = 0;;
};
class Solution {
public:
  int numberOfUniqueGoodSubsequences(string binary) {
    vector<C1097Int<>> pre(2);
    for (const auto& ch : binary)
    {
      pre = {('0'==ch)? (pre[0] + pre[1]):pre[0],('1' == ch) ? (pre[0] + pre[1]+1) : pre[1] };
    }
    int iZero = std::count(binary.begin(), binary.end(), '0') > 0;
    return (pre[0] + pre[1] + iZero).ToInt();
  }
};

2023年2月

class C1097Int

{

public:

C1097Int(int iData = 0) :m_iData(iData)

{

}

C1097Int operator+(const C1097Int& o)const

{

return C1097Int(((long long)m_iData + o.m_iData) % s_iMod);

}

C1097Int& operator+=(const C1097Int& o)

{

m_iData = ((long long)m_iData + o.m_iData) % s_iMod;

return this;
}
C1097Int operator
(const C1097Int& o)const

{

return((long long)m_iData o.m_iData) % s_iMod;
}
C1097Int& operator
=(const C1097Int& o)

{

m_iData =((long long)m_iData *o.m_iData) % s_iMod;

return *this;

}

bool operator<(const C1097Int& o)const

{

return m_iData < o.m_iData;

}

C1097Int& pow( int n)const

{

C1097Int iRet = 1, iCur = *this;

while (n)

{

if (n & 1)

{

iRet *= iCur;

}

iCur *= iCur;

n >>= 1;

}

return iRet;

}

C1097Int PowNegative1()

{

return pow(s_iMod - 2);

}

int ToInt()const

{

return m_iData;

}

private:

int m_iData = 0;;

static const int s_iMod = 1000000007;

};

int operator+(int iData, const C1097Int& int1097)

{

int iRet = int1097.operator+(C1097Int(iData)).ToInt();

return iRet;

}

int& operator+=(int& iData, const C1097Int& int1097)

{

iData = int1097.operator+(C1097Int(iData)).ToInt();

return iData;

}

int operator*(int iData, const C1097Int& int1097)

{

int iRet = int1097.operator*(C1097Int(iData)).ToInt();

return iRet;

}

int& operator*=(int& iData, const C1097Int& int1097)

{

iData = int1097.operator*(C1097Int(iData)).ToInt();

return iData;

}

class Solution {

public:

int numberOfUniqueGoodSubsequences(string binary) {

vector pre(2);

for (const auto& ch : binary)

{

vector dp(2);

if (‘0’ == ch)

{

pre[0] += pre[1];

}

else

{

pre[1] += pre[0];

pre[1] += 1;

}

}

return (pre[0] + pre[1] + (int)(-1 != binary.find(‘0’))).ToInt();

}

};

2023年7月

class Solution {

public:

int numberOfUniqueGoodSubsequences(string binary) {

bool bHasZero = binary[0] == ‘0’;

vector<C1097Int<>> pre(2);

pre[1] = (binary[0] == ‘1’);

for (int i = 1; i < binary.size(); i++)

{

vector<C1097Int<>> dp = pre ;

if (‘0’ == binary[i])

{

bHasZero = true;

dp[0] = pre[0] + pre[1];

}

else

{

dp[1] = pre[0] + pre[1] + 1;

}

pre.swap(dp);

}

return (C1097Int<>(bHasZero) + pre[0] + pre[1]).ToInt();

}

};


相关文章
|
7月前
|
机器学习/深度学习 存储 算法
动态规划算法深度解析:0-1背包问题
0-1背包问题是经典的组合优化问题,目标是在给定物品重量和价值及背包容量限制下,选取物品使得总价值最大化且每个物品仅能被选一次。该问题通常采用动态规划方法解决,通过构建二维状态表dp[i][j]记录前i个物品在容量j时的最大价值,利用状态转移方程避免重复计算子问题,从而高效求解最优解。
818 1
|
11月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
222 2
|
11月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
277 17
|
9月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
242 0
|
10月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
290 0
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
257 4
|
存储 算法 安全
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
273 8
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
472 12
|
10月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
254 0
下一篇
开通oss服务