📌  相关文章
📜  最小化交替子序列的计数以将给定的二进制字符串与子序列号相除

📅  最后修改于: 2022-05-13 01:56:07.698000             🧑  作者: Mango

最小化交替子序列的计数以将给定的二进制字符串与子序列号相除

给定一个长度为N的二进制字符串S。任务是找到以下内容:

  • 子序列的最小数目,字符串S可以被划分,使得子序列不包含相邻的零或一。
  • 字符串S的每个字符所属的子序列号。

如果有很多答案,则输出任何答案。

例子:

方法:需要注意的是,子序列是可以通过删除零个或多个元素而不改变剩余元素的顺序从给定序列导出的序列。现在,请按照以下步骤解决问题:

  1. 创建一个向量ans来存储字符串S的每个字符所属的子序列。
  2. 另外,创建两个向量endZeroendOne分别存储以“0”“1”结尾的子序列。
  3. 因为子序列中不能有相邻的零或一。因此,如果一个字符是'0' ,则要放入子序列中的下一个字符必须是'1' ,反之亦然。
  4. 现在,使用循环遍历S的每个字符并检查它是'0'还是'1' 。此外,声明一个变量newSeq ,它表示如果遇到连续的零或一,则要形成的新子序列。
  5. 如果一个字符是'0' ,检查向量endOne是否为空:
    • 如果为空,则将newSeq推入endZero
    • 否则,将endOne的最后一个子序列放入newSeq中。现在, endOne的最后一个子序列不再以'1'结尾,因为它已附加了'0' 。因此,将其推入endZero
  6. 同样,如果S中的字符为'1' ,则执行与上述相同的步骤,即检查向量endZero是否为空:
    • 如果为空,则将newSeq推入endOne
    • 否则,将endZero的最后一个子序列放入newSeq中。现在, endZero的最后一个子序列不再以“0”结尾,因为“1”已附加到它上面。因此,将其推入endOne
  7. 然后,将newSeq推入向量ans中。
  8. S的每个字符重复上述步骤。
  9. 子序列的最小数量将由endZeroendOne的大小之和给出。
  10. 最后,输出最小子序列数和向量ans

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the minimum number of
// subsequences into which S has to divide
// and the subsequences to which each character
// of S belongs to.
void findSeq(string S, int N)
{
    // Stores the subsequences to which each
    // character of S belongs to.
    vector ans(N);
 
    // Store the subsequences ending with zeroes
    // and ones respectively.
    vector endZero, endOne;
 
    // Loop to traverse each character of S
    for (int i = 0; i < N; ++i) {
 
        // Stores the number of new
        // subsequence to be formed
        int newSeq = endZero.size()
                     + endOne.size();
 
        // If the character is '0'
        if (S[i] == '0') {
 
            // If there is no string
            // which ends with '1'
            if (endOne.empty()) {
 
                // Push newSeq into endZero
                endZero.push_back(newSeq);
            }
            else {
 
                // Put the last element
                // of endOne into newSeq
                newSeq = endOne.back();
 
                // Remove the last
                // element of endOne
                endOne.pop_back();
 
                // newSeq ends with '0'
                endZero.push_back(newSeq);
            }
        }
        else {
 
            // If there is no string
            // which ends with '0'
            if (endZero.empty()) {
 
                // Push newSeq into endOne
                endOne.push_back(newSeq);
            }
            else {
 
                // Put the last element
                // of endZero into newSeq
                newSeq = endZero.back();
 
                // Remove the last element of endOne
                endZero.pop_back();
 
                // newSeq ends with '1'
                endOne.push_back(newSeq);
            }
        }
 
        // Put newSeq into vector ans
        ans[i] = newSeq;
    }
 
    // Output the minimum
    // number of subsequences
    cout << endZero.size()
                + endOne.size()
         << endl;
 
    // Output the subsequences
    // to which each character
    // of S belongs to
    for (int i = 0; i < N; ++i) {
 
        // Add 1 as the index starts from 0
        cout << ans[i] + 1 << " ";
    }
}
 
// Driver Code
int main()
{
 
    // Given input
    string S = "1000110";
    int N = 7;
 
    // Function Call
    findSeq(S, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.ArrayList;
 
class GFG {
 
    // Function to find the minimum number of
    // subsequences into which S has to divide
    // and the subsequences to which each character
    // of S belongs to.
    public static void findSeq(String S, int N)
    {
       
        // Stores the subsequences to which each
        // character of S belongs to.
        int[] ans = new int[N];
 
        // Store the subsequences ending with zeroes
        // and ones respectively.
        ArrayList endZero = new ArrayList();
        ArrayList endOne = new ArrayList();
 
        // Loop to traverse each character of S
        for (int i = 0; i < N; ++i) {
 
            // Stores the number of new
            // subsequence to be formed
            int newSeq = endZero.size() + endOne.size();
 
            // If the character is '0'
            if (S.charAt(i) == '0') {
 
                // If there is no string
                // which ends with '1'
                if (endOne.isEmpty()) {
 
                    // Push newSeq into endZero
                    endZero.add(newSeq);
                } else {
 
                    // Put the last element
                    // of endOne into newSeq
                    newSeq = endOne.get(endOne.size() - 1);
 
                    // Remove the last
                    // element of endOne
                    endOne.remove(endOne.size() - 1);
 
                    // newSeq ends with '0'
                    endZero.add(newSeq);
                }
            } else {
 
                // If there is no string
                // which ends with '0'
                if (endZero.isEmpty()) {
 
                    // Push newSeq into endOne
                    endOne.add(newSeq);
                } else {
 
                    // Put the last element
                    // of endZero into newSeq
                    newSeq = endZero.get(endZero.size() - 1);
 
                    // Remove the last element of endOne
                    endZero.remove(endZero.size() - 1);
 
                    // newSeq ends with '1'
                    endOne.add(newSeq);
                }
            }
 
            // Put newSeq into vector ans
            ans[i] = newSeq;
        }
 
        // Output the minimum
        // number of subsequences
        System.out.println(endZero.size() + endOne.size());
 
        // Output the subsequences
        // to which each character
        // of S belongs to
        for (int i = 0; i < N; ++i) {
 
            // Add 1 as the index starts from 0
            System.out.print(ans[i] + 1 + " ");
        }
    }
 
    // Driver Code
    public static void main(String args[]) {
 
        // Given input
        String S = "1000110";
        int N = 7;
 
        // Function Call
        findSeq(S, N);
 
    }
}
 
// This code is contributed by gfgking.


Python3
# python program for the above approach
 
# Function to find the minimum number of
# subsequences into which S has to divide
# and the subsequences to which each character
# of S belongs to.
def findSeq(S, N):
 
    # Stores the subsequences to which each
    # character of S belongs to.
    ans = [0 for _ in range(N)]
 
    # Store the subsequences ending with zeroes
    # and ones respectively.
    endZero = []
    endOne = []
 
    # Loop to traverse each character of S
    for i in range(0, N):
 
         # Stores the number of new
         # subsequence to be formed
        newSeq = len(endZero) + len(endOne)
 
        # If the character is '0'
        if (S[i] == '0'):
 
             # If there is no string
             # which ends with '1'
            if (len(endOne) == 0):
 
                # Push newSeq into endZero
                endZero.append(newSeq)
 
            else:
 
               # Put the last element
                # of endOne into newSeq
                newSeq = endOne[len(endOne) - 1]
 
                # Remove the last
                # element of endOne
                endOne.pop()
 
                # newSeq ends with '0'
                endZero.append(newSeq)
 
        else:
 
            # If there is no string
            # which ends with '0'
            if (len(endZero) == 0):
 
                # Push newSeq into endOne
                endOne.append(newSeq)
 
            else:
 
                 # Put the last element
                # of endZero into newSeq
                newSeq = endZero[len(endZero) - 1]
 
                # Remove the last element of endOne
                endZero.pop()
 
                # newSeq ends with '1'
                endOne.append(newSeq)
 
                # Put newSeq into vector ans
        ans[i] = newSeq
 
        # Output the minimum
        # number of subsequences
    print(len(endZero) + len(endOne))
 
    # Output the subsequences
    # to which each character
    # of S belongs to
    for i in range(0, N):
 
        # Add 1 as the index starts from 0
        print(ans[i] + 1, end=" ")
 
# Driver Code
if __name__ == "__main__":
 
        # Given input
    S = "1000110"
    N = 7
 
    # Function Call
    findSeq(S, N)
 
    # This code is contributed by rakeshsahni


C#
// C# program for the above approach
 
using System;
using System.Collections.Generic;
class GFG
{
 
    // Function to find the minimum number of
    // subsequences into which S has to divide
    // and the subsequences to which each character
    // of S belongs to.
    public static void findSeq(String S, int N)
    {
 
        // Stores the subsequences to which each
        // character of S belongs to.
        int[] ans = new int[N];
 
        // Store the subsequences ending with zeroes
        // and ones respectively.
        List endZero = new List();
        List endOne = new List();
 
        // Loop to traverse each character of S
        for (int i = 0; i < N; ++i)
        {
 
            // Stores the number of new
            // subsequence to be formed
            int newSeq = endZero.Count + endOne.Count;
 
            // If the character is '0'
            if (S[i] == '0')
            {
 
                // If there is no string
                // which ends with '1'
                if (endOne.Count == 0)
                {
 
                    // Push newSeq into endZero
                    endZero.Add(newSeq);
                }
                else
                {
 
                    // Put the last element
                    // of endOne into newSeq
                    newSeq = endOne[endOne.Count - 1];
 
                    // Remove the last
                    // element of endOne
                    endOne.Remove(endOne.Count - 1);
 
                    // newSeq ends with '0'
                    endZero.Add(newSeq);
                }
            }
            else
            {
 
                // If there is no string
                // which ends with '0'
                if (endZero.Count == 0)
                {
 
                    // Push newSeq into endOne
                    endOne.Add(newSeq);
                }
                else
                {
 
                    // Put the last element
                    // of endZero into newSeq
                    newSeq = endZero[endZero.Count - 1];
 
                    // Remove the last element of endOne
                    endZero.Remove(endZero.Count - 1);
 
                    // newSeq ends with '1'
                    endOne.Add(newSeq);
                }
            }
 
            // Put newSeq into vector ans
            ans[i] = newSeq;
        }
 
        // Output the minimum
        // number of subsequences
        Console.WriteLine(endZero.Count + endOne.Count);
 
        // Output the subsequences
        // to which each character
        // of S belongs to
        for (int i = 0; i < N; ++i)
        {
 
            // Add 1 as the index starts from 0
            Console.Write(ans[i] + 1 + " ");
        }
    }
 
    // Driver Code
    public static void Main()
    {
 
        // Given input
        String S = "1000110";
        int N = 7;
 
        // Function Call
        findSeq(S, N);
 
    }
}
 
// This code is contributed by gfgking.


Javascript


输出
3
1 1 2 3 3 2 2 

时间复杂度: O(N)
辅助空间: O(N)