二进制字符串中 0*1*0* 形式的最长子序列
给定一个二进制字符串,找出其中最长的 (0)*(1)*(0)* 子序列。基本上我们需要将字符串分成 3 个不重叠的字符串(这些字符串可能是空的)而不改变字母的顺序。第一个和第三个字符串仅由0组成,第二个字符串仅由 1 组成。这些字符串可以通过删除原始字符串中的一些字符来组成。 字符串的最大大小是多少,我们可以得到?
例子:
Input : 000011100000
Output : 12
Explanation :
First part from 1 to 4.
Second part 5 to 7.
Third part from 8 to 12
Input : 100001100
Output : 8
Explanation :
Delete the first letter.
First part from 2 to 4.
Second part from 5 to 6.
Last part from 7.
Input : 00000
Output : 5
Explanation :
Special Case of Only 0
Input : 111111
Output : 6
Explanation :
Special Case of Only 1
Input : 0000001111011011110000
Output : 20
Explanation :
Second part is from 7 to 18.
Remove all the 0 between indices 7 to 18.
一个简单的解决方案是生成给定序列的所有子序列。对于每个子序列,检查它是否是给定的形式。如果是,请将其与迄今为止的结果进行比较,并在需要时更新结果。
这个问题可以通过在O(n^2) 时间内预先计算下面的数组来有效地解决。
令 pre_count_0[i] 为字符串前缀中字母 0 的计数,直到索引 i。
令 pre_count_1[i] 为字符串前缀中字母 1 的计数,直到长度为 i。
令 post_count_0[i] 为从索引 i 到索引 n 的后缀字符串中字母 0 的计数(这里 n 是字符串的大小)。
现在我们固定两个两个位置 i 和 j,1 <=i <= j <=n。我们将从索引 i 开始并以索引 j 结束的子字符串中删除所有 0。因此,这使得第二个子字符串只有 1。在索引 i 之前的前缀和索引 j 之后的后缀中,我们将删除所有 1,因此它将成为字符串的第一部分和第三部分。
那么可达到的最大字符串长度为
pre_count_0[i-1] + (pre_count_1[j]-pre_count_1[i-1]) + pre_count_1[j+1]
特殊情况:当 String 仅由 0 或 1 组成时,ans 是 n,其中 n 是字符串的长度。
C++
// CPP program to find longest subsequence
// of the form 0*1*0* in a binary string
#include
using namespace std;
// Returns length of the longest subsequence
// of the form 0*1*0*
int longestSubseq(string s)
{
int n = s.length();
// Precomputing values in three arrays
// pre_count_0[i] is going to store count
// of 0s in prefix str[0..i-1]
// pre_count_1[i] is going to store count
// of 1s in prefix str[0..i-1]
// post_count_0[i] is going to store count
// of 0s in suffix str[i-1..n-1]
int pre_count_0[n + 2];
int pre_count_1[n + 1];
int post_count_0[n + 1];
pre_count_0[0] = 0;
post_count_0[n + 1] = 0;
pre_count_1[0] = 0;
for (int j = 1; j <= n; j++)
{
pre_count_0[j] = pre_count_0[j - 1];
pre_count_1[j] = pre_count_1[j - 1];
post_count_0[n - j + 1] = post_count_0[n - j + 2];
if (s[j - 1] == '0')
pre_count_0[j]++;
else
pre_count_1[j]++;
if (s[n - j] == '0')
post_count_0[n - j + 1]++;
}
// string is made up of all 0s or all 1s
if (pre_count_0[n] == n ||
pre_count_0[n] == 0)
return n;
// Compute result using precomputed values
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
ans = max(pre_count_0[i - 1]
+ pre_count_1[j]
- pre_count_1[i - 1]
+ post_count_0[j + 1],
ans);
return ans;
}
// driver program
int main()
{
string s = "000011100000";
cout << longestSubseq(s);
return 0;
}
Java
// Java program to find longest subsequence
// of the form 0*1*0* in a binary string
class GFG
{
// Returns length of the longest subsequence
// of the form 0*1*0*
public static int longestSubseq(String s)
{
int n = s.length();
// Precomputing values in three arrays
// pre_count_0[i] is going to store count
// of 0s in prefix str[0..i-1]
// pre_count_1[i] is going to store count
// of 1s in prefix str[0..i-1]
// post_count_0[i] is going to store count
// of 0s in suffix str[i-1..n-1]
int[] pre_count_0 = new int[n + 2];
int[] pre_count_1 = new int[n + 1];
int[] post_count_0 = new int[n + 2];
pre_count_0[0] = 0;
post_count_0[n + 1] = 0;
pre_count_1[0] = 0;
for (int j = 1; j <= n; j++)
{
pre_count_0[j] = pre_count_0[j - 1];
pre_count_1[j] = pre_count_1[j - 1];
post_count_0[n - j + 1] = post_count_0[n - j + 2];
if (s.charAt(j - 1) == '0')
pre_count_0[j]++;
else
pre_count_1[j]++;
if (s.charAt(n - j) == '0')
post_count_0[n - j + 1]++;
}
// string is made up of all 0s or all 1s
if (pre_count_0[n] == n ||
pre_count_0[n] == 0)
return n;
// Compute result using precomputed values
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
ans = Math.max(pre_count_0[i - 1] +
pre_count_1[j] -
pre_count_1[i - 1] +
post_count_0[j + 1], ans);
return ans;
}
// Driver code
public static void main(String[] args)
{
String s = "000011100000";
System.out.println(longestSubseq(s));
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python 3 program to find longest subsequence
# of the form 0*1*0* in a binary string
# Returns length of the longest subsequence
# of the form 0*1*0*
def longestSubseq(s):
n = len(s)
# Precomputing values in three arrays
# pre_count_0[i] is going to store count
# of 0s in prefix str[0..i-1]
# pre_count_1[i] is going to store count
# of 1s in prefix str[0..i-1]
# post_count_0[i] is going to store count
# of 0s in suffix str[i-1..n-1]
pre_count_0 = [0 for i in range(n + 2)]
pre_count_1 = [0 for i in range(n + 1)]
post_count_0 = [0 for i in range(n + 2)]
pre_count_0[0] = 0
post_count_0[n + 1] = 0
pre_count_1[0] = 0
for j in range(1, n + 1):
pre_count_0[j] = pre_count_0[j - 1]
pre_count_1[j] = pre_count_1[j - 1]
post_count_0[n - j + 1] = post_count_0[n - j + 2]
if (s[j - 1] == '0'):
pre_count_0[j] += 1
else:
pre_count_1[j] += 1
if (s[n - j] == '0'):
post_count_0[n - j + 1] += 1
# string is made up of all 0s or all 1s
if (pre_count_0[n] == n or
pre_count_0[n] == 0):
return n
# Compute result using precomputed values
ans = 0
for i in range(1, n + 1):
for j in range(i, n + 1, 1):
ans = max(pre_count_0[i - 1] +
pre_count_1[j] -
pre_count_1[i - 1] +
post_count_0[j + 1], ans)
return ans
# Driver Code
if __name__ == '__main__':
s = "000011100000"
print(longestSubseq(s))
# This code is contributed by
# Surendra_Gangwar
C#
// C# program to find longest subsequence
// of the form 0*1*0* in a binary string
using System;
class GFG
{
// Returns length of the longest subsequence
// of the form 0*1*0*
public static int longestSubseq(String s)
{
int n = s.Length;
// Precomputing values in three arrays
// pre_count_0[i] is going to store count
// of 0s in prefix str[0..i-1]
// pre_count_1[i] is going to store count
// of 1s in prefix str[0..i-1]
// post_count_0[i] is going to store count
// of 0s in suffix str[i-1..n-1]
int[] pre_count_0 = new int[n + 2];
int[] pre_count_1 = new int[n + 1];
int[] post_count_0 = new int[n + 2];
pre_count_0[0] = 0;
post_count_0[n + 1] = 0;
pre_count_1[0] = 0;
for (int j = 1; j <= n; j++)
{
pre_count_0[j] = pre_count_0[j - 1];
pre_count_1[j] = pre_count_1[j - 1];
post_count_0[n - j + 1] = post_count_0[n - j + 2];
if (s[j - 1] == '0')
pre_count_0[j]++;
else
pre_count_1[j]++;
if (s[n - j] == '0')
post_count_0[n - j + 1]++;
}
// string is made up of all 0s or all 1s
if (pre_count_0[n] == n ||
pre_count_0[n] == 0)
return n;
// Compute result using precomputed values
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
ans = Math.Max(pre_count_0[i - 1] +
pre_count_1[j] -
pre_count_1[i - 1] +
post_count_0[j + 1], ans);
return ans;
}
// Driver code
public static void Main(String[] args)
{
String s = "000011100000";
Console.WriteLine(longestSubseq(s));
}
}
// This code is contributed by Princi Singh
Javascript
输出 :
12