给定一个长度为N的二进制字符串S ,任务是找到其中可以被3整除的最长子序列的长度。子序列中允许有前导零。
例子:
Input: S = “1001”
Output: 4
The longest sub-sequence divisible by 3 is “1001”.
1001 = 9 which is divisible by 3.
Input: S = “1011”
Output: 3
天真的方法:生成所有可能的子序列并检查它们是否可以被3整除。时间复杂度为O((2 N ) * N) 。
有效的方法:可以使用动态规划来解决这个问题。让我们看看DP的状态。
DP[i][r]将存储子串S[i…N-1]的最长子序列,这样当除以3时它给出的余数为(3 – r) % 3 。
现在让我们写下递推关系。
DP[i][r] = max(1 + DP[i + 1][(r * 2 + s[i]) % 3], DP[i + 1][r])
由于以下两个选择,推导出递归:
- 在子序列中包含当前索引i 。因此, r将更新为r = (r * 2 + s[i]) % 3 。
- 不要在子序列中包含当前索引。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define N 100
int dp[N][3];
bool v[N][3];
// Function to return the length of the
// largest sub-string divisible by 3
int findLargestString(string& s, int i, int r)
{
// Base-case
if (i == s.size()) {
if (r == 0)
return 0;
else
return INT_MIN;
}
// 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]
= max(1 + findLargestString(s, i + 1,
(r * 2 + (s[i] - '0')) % 3),
findLargestString(s, i + 1, r));
return dp[i][r];
}
// Driver code
int main()
{
string s = "101";
cout << findLargestString(s, 0, 0);
return 0;
}
Java
// Java implementation of th approach
class GFG
{
final static int N = 100 ;
final static int INT_MIN = Integer.MIN_VALUE;
static int dp[][] = new int[N][3];
static int v[][] = new int[N][3];
// Function to return the length of the
// largest sub-string divisible by 3
static int findLargestString(String s, int i, int r)
{
// Base-case
if (i == s.length())
{
if (r == 0)
return 0;
else
return INT_MIN;
}
// 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] = Math.max(1 + findLargestString(s, i + 1,
(r * 2 + (s.charAt(i) - '0')) % 3),
findLargestString(s, i + 1, r));
return dp[i][r];
}
// Driver code
public static void main (String[] args)
{
String s = "101";
System.out.print(findLargestString(s, 0, 0));
}
}
// This code is contributed by AnkitRai01
Python3
# Python3 implementation of the approach
import numpy as np
import sys
N = 100
INT_MIN = -(sys.maxsize - 1)
dp = np.zeros((N, 3));
v = np.zeros((N, 3));
# Function to return the length of the
# largest sub-string divisible by 3
def findLargestString(s, i, r) :
# Base-case
if (i == len(s)) :
if (r == 0) :
return 0;
else :
return INT_MIN;
# 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] = max(1 + findLargestString(s, i + 1,
(r * 2 + (ord(s[i]) - ord('0'))) % 3),
findLargestString(s, i + 1, r));
return dp[i][r];
# Driver code
if __name__ == "__main__" :
s = "101";
print(findLargestString(s, 0, 0));
# This code is contributed by AnkitRai01
C#
// C# implementation of th approach
using System;
using System.Collections.Generic;
class GFG
{
readonly static int N = 100 ;
readonly static int INT_MIN = int.MinValue;
static int [,]dp = new int[N, 3];
static int [,]v = new int[N, 3];
// Function to return the length of the
// largest sub-string divisible by 3
static int findLargestString(String s, int i, int r)
{
// Base-case
if (i == s.Length)
{
if (r == 0)
return 0;
else
return INT_MIN;
}
// 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] = Math.Max(1 + findLargestString(s, i + 1,
(r * 2 + (s[i] - '0')) % 3),
findLargestString(s, i + 1, r));
return dp[i, r];
}
// Driver code
public static void Main(String[] args)
{
String s = "101";
Console.Write(findLargestString(s, 0, 0));
}
}
// This code is contributed by 29AjayKumar
Javascript
输出:
2
时间复杂度: O(n)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。