📌  相关文章
📜  二进制字符串的非零长度的子序列数可被3整除

📅  最后修改于: 2021-04-29 18:32:30             🧑  作者: Mango

给定长度为N的二进制字符串S ,任务是找到非零长度的子序列数,该子序列数可被3整除。子序列中的前导零是允许的。

例子:

天真的方法:生成所有可能的子序列,并检查它们是否可被3整除。其时间复杂度为O((2 N )* N)。

更好的方法:可以使用动态编程来解决此问题。让我们看一下DP的状态。
DP [I] [R]将存储子串S的子序列的数目[1 … N-1],使得它们得到的(3 – r)的余数%3当除以3。
现在让我们编写递归关系。

由于以下两个选择而导致重复发生:

  1. 在子序列中包括当前索引i 。因此, r将更新为r =(r * 2 + s [i])%3
  2. 不要在子序列中包括当前索引。

下面是上述方法的实现:

C++
// C++ implementation of th approach
#include 
using namespace std;
#define N 100
  
int dp[N][3];
bool v[N][3];
  
// Function to return the number of
// sub-sequences divisible by 3
int findCnt(string& s, int i, int r)
{
    // Base-cases
    if (i == s.size()) {
        if (r == 0)
            return 1;
        else
            return 0;
    }
  
    // If the state has been solved
    // before then return its value
    if (v[i][r])
        return dp[i][r];
  
    // Marking the state as solved
    v[i][r] = 1;
  
    // Recurrence relation
    dp[i][r]
        = findCnt(s, i + 1, (r * 2 + (s[i] - '0')) % 3)
          + findCnt(s, i + 1, r);
  
    return dp[i][r];
}
  
// Driver code
int main()
{
    string s = "11";
  
    cout << (findCnt(s, 0, 0) - 1);
  
    return 0;
}


Java
// Java implementation of th approach 
class GFG 
{
  
    static final int N = 100; 
      
    static int dp[][] = new int[N][3]; 
    static int v[][] = new int[N][3]; 
      
    // Function to return the number of 
    // sub-sequences divisible by 3 
    static int findCnt(String s, int i, int r) 
    { 
        // Base-cases 
        if (i == s.length()) 
        { 
            if (r == 0) 
                return 1; 
            else
                return 0; 
        } 
      
        // If the state has been solved 
        // before then return its value 
        if (v[i][r] == 1) 
            return dp[i][r]; 
      
        // Marking the state as solved 
        v[i][r] = 1; 
      
        // Recurrence relation 
        dp[i][r] = findCnt(s, i + 1, (r * 2 + (s.charAt(i) - '0')) % 3) 
                    + findCnt(s, i + 1, r); 
      
        return dp[i][r]; 
    }
      
    // Driver code 
    public static void main (String[] args) 
    {
        String s = "11"; 
      
        System.out.print(findCnt(s, 0, 0) - 1); 
      
    } 
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 implementation of th approach 
import numpy as np
N = 100
  
dp = np.zeros((N, 3)); 
v = np.zeros((N, 3));
  
# Function to return the number of 
# sub-sequences divisible by 3 
def findCnt(s, i, r) :
  
    # Base-cases 
    if (i == len(s)) : 
          
        if (r == 0) :
            return 1; 
        else :
            return 0; 
  
    # If the state has been solved 
    # before then return its value 
    if (v[i][r]) :
        return dp[i][r]; 
  
    # Marking the state as solved 
    v[i][r] = 1; 
  
    # Recurrence relation 
    dp[i][r] = findCnt(s, i + 1, (r * 2 + 
                      (ord(s[i]) - ord('0'))) % 3) + \
               findCnt(s, i + 1, r); 
  
    return dp[i][r]; 
  
# Driver code 
if __name__ == "__main__" : 
  
    s = "11"; 
  
    print(findCnt(s, 0, 0) - 1); 
  
# This code is contributed by AnkitRai01


C#
// C# implementation of th approach 
using System;
  
class GFG 
{
  
    static readonly int N = 100; 
      
    static int [,]dp = new int[N, 3]; 
    static int [,]v = new int[N, 3]; 
      
    // Function to return the number of 
    // sub-sequences divisible by 3 
    static int findCnt(String s, int i, int r) 
    { 
        // Base-cases 
        if (i == s.Length) 
        { 
            if (r == 0) 
                return 1; 
            else
                return 0; 
        } 
      
        // If the state has been solved 
        // before then return its value 
        if (v[i, r] == 1) 
            return dp[i, r]; 
      
        // Marking the state as solved 
        v[i, r] = 1; 
      
        // Recurrence relation 
        dp[i, r] = findCnt(s, i + 1, (r * 2 + (s[i] - '0')) % 3) 
                    + findCnt(s, i + 1, r); 
      
        return dp[i, r]; 
    }
      
    // Driver code 
    public static void Main(String[] args) 
    {
        String s = "11"; 
      
        Console.Write(findCnt(s, 0, 0) - 1); 
      
    } 
}
  
// This code is contributed by 29AjayKumar


输出:
1

时间复杂度: O(n)