📌  相关文章
📜  计算分割字符串,使两个部分具有相同的不同字符

📅  最后修改于: 2021-09-22 09:55:34             🧑  作者: Mango

给定一个字符串S ,任务是计算将字符串分成两个非空部分的方法的数量,使得这两个部分具有相同数量的不同字符。

例子:

朴素的方法:这个想法是选择字符串的每个可能的分区点,并为每个分区计算分区字符串的不同字符。如果两个分区字符串中不同字符的数量相等,则将路数增加 1。
下面是上述方法的实现:

C++
// C++ implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
 
#include 
 
using namespace std;
 
// Function to count the distinct
// characters in the string
int distinctChars(string s)
{
    // Frequency of each character
    int freq[26] = { 0 };
    int count = 0;
     
    // Loop to count the frequency
    // of each character of the string
    for (int i = 0; i < s.length(); i++)
        freq[s[i] - 'a']++;
 
    // If frequency is greater than 0
    // then the character occured
    for (int i = 0; i < 26; i++) {
        if (freq[i] > 0)
            count++;
    }
 
    return count;
}
 
// Function to count the number
// of ways to partition the string
// such that each partition have
// same number of distinct character
int waysToSplit(string s)
{
    int n = s.length();
    int answer = 0;
     
    // Loop to choose the partition
    // index for the string
    for (int i = 1; i < n; i++) {
         
        // Divide in two parts
        string left = s.substr(0, i);
        string right = s.substr(i, n - i);
 
        // Check whether number of distinct
        // characters are equal
        if (distinctChars(left) ==
             distinctChars(right))
            answer++;
    }
    return answer;
}
 
// Driver Code
int main()
{
    string s = "ababa";
 
    cout << waysToSplit(s);
    return 0;
}


Java
// Java implementation to count the
// number of ways to partition the
// String such that each partition
// have same number of distinct
// characters in the String
class GFG{
  
// Function to count the distinct
// characters in the String
static int distinctChars(String s)
{
    // Frequency of each character
    int freq[] = new int[26];
    int count = 0;
      
    // Loop to count the frequency
    // of each character of the String
    for (int i = 0; i < s.length(); i++)
        freq[s.charAt(i) - 'a']++;
  
    // If frequency is greater than 0
    // then the character occured
    for (int i = 0; i < 26; i++) {
        if (freq[i] > 0)
            count++;
    }
  
    return count;
}
  
// Function to count the number
// of ways to partition the String
// such that each partition have
// same number of distinct character
static int waysToSplit(String s)
{
    int n = s.length();
    int answer = 0;
      
    // Loop to choose the partition
    // index for the String
    for (int i = 1; i < n; i++) {
          
        // Divide in two parts
        String left = s.substring(0, i);
        String right = s.substring(i, n);
  
        // Check whether number of distinct
        // characters are equal
        if (distinctChars(left) ==
             distinctChars(right))
            answer++;
    }
    return answer;
}
  
// Driver Code
public static void main(String[] args)
{
    String s = "ababa";
  
    System.out.print(waysToSplit(s));
}
}
 
// This code is contributed by sapnasingh4991


Python3
# Python3 implementation to count the
# number of ways to partition the
# string such that each partition
# have same number of distinct
# characters in the string
 
# Function to count the distinct
# characters in the string
def distinctChars(s) :
 
    # Frequency of each character
    freq = [0]*26;
    count = 0;
     
    # Loop to count the frequency
    # of each character of the string
    for i in range(len(s)) :
        freq[ord(s[i]) - ord('a')] += 1;
 
    # If frequency is greater than 0
    # then the character occured
    for i in range(26) :
        if (freq[i] > 0) :
            count += 1;
 
    return count;
 
# Function to count the number
# of ways to partition the string
# such that each partition have
# same number of distinct character
def waysToSplit(s) :
    n = len(s);
    answer = 0;
     
    # Loop to choose the partition
    # index for the string
    for i in range(1, n) :
         
        # Divide in two parts
        left = s[0 : i];
        right = s[i : n ];
 
        # Check whether number of distinct
        # characters are equal
        if (distinctChars(left) == distinctChars(right)) :
            answer += 1;
     
    return answer;
 
# Driver Code
if __name__ == "__main__" :
 
    s = "ababa";
 
    print(waysToSplit(s));
     
# This code is contributed by Yash_R


C#
// C# implementation to count the
// number of ways to partition the
// String such that each partition
// have same number of distinct
// characters in the String
using System;
 
class GFG{
  
// Function to count the distinct
// characters in the String
static int distinctChars(string s)
{
    // Frequency of each character
    int []freq = new int[26];
    int count = 0;
      
    // Loop to count the frequency
    // of each character of the String
    for (int i = 0; i < s.Length; i++)
        freq[s[i] - 'a']++;
  
    // If frequency is greater than 0
    // then the character occured
    for (int i = 0; i < 26; i++) {
        if (freq[i] > 0)
            count++;
    }
  
    return count;
}
  
// Function to count the number
// of ways to partition the String
// such that each partition have
// same number of distinct character
static int waysToSplit(string s)
{
    int n = s.Length;
    int answer = 0;
      
    // Loop to choose the partition
    // index for the String
    for (int i = 1; i < n; i++) {
          
        // Divide in two parts
        string left = s.Substring(0, i);
        string right = s.Substring(i, n-i);
  
        // Check whether number of distinct
        // characters are equal
        if (distinctChars(left) ==
             distinctChars(right))
            answer++;
    }
    return answer;
}
  
// Driver Code
public static void Main(string[] args)
{
    string s = "ababa";
  
    Console.WriteLine(waysToSplit(s));
}
}
 
// This code is contributed by Yash_R


Javascript


C++
// C++ implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
 
#include 
 
using namespace std;
 
// Function to count the number
// of ways to partition the string
// such that each partition have
// same number of distinct character
int waysToSplit(string s)
{
    int n = s.length();
    int answer = 0;
     
    // Prefix and suffix array for
    // distinct character from
    // start and end
    int prefix[n] = { 0 };
    int suffix[n] = { 0 };
 
    // To check whether a character
    // has appeared till ith index
    int seen[26] = { 0 };
 
    // Calculating prefix array
    for (int i = 0; i < n; i++) {
 
        int prev = (i - 1 >= 0 ?
              prefix[i - 1] : 0);
 
        // Character appears for
        // the first time in string
        if (seen[s[i] - 'a'] == 0) {
            prefix[i] += (prev + 1);
        }
        else
            prefix[i] = prev;
 
        // Character is visited
        seen[s[i] - 'a'] = 1;
    }
     
    // Resetting seen for
    // suffix calculation
    memset(seen, 0, sizeof(seen));
 
    // Calculating the suffix array
    suffix[n - 1] = 0;
    for (int i = n - 1; i >= 1; i--) {
        int prev = suffix[i];
 
        // Character appears
        // for the first time
        if (seen[s[i] - 'a'] == 0) {
            suffix[i - 1] += (prev + 1);
        }
        else
            suffix[i - 1] = prev;
 
        // This character
        // has now appeared
        seen[s[i] - 'a'] = 1;
    }
     
    // Loop to calculate the number
    // partition points in the string
    for (int i = 0; i < n; i++) {
        // Check whether number of
        // distinct characters are equal
        if (prefix[i] == suffix[i])
            answer++;
    }
    return answer;
}
 
// Driver Code
int main()
{
    string s = "ababa";
 
    cout << waysToSplit(s);
    return 0;
}


Java
// Java implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
class GFG {
     
    // Function to count the number
    // of ways to partition the string
    // such that each partition have
    // same number of distinct character
    static int waysToSplit(String s)
    {
        int n = s.length();
        int answer = 0;
         
        // Prefix and suffix array for
        // distinct character from
        // start and end
        int prefix[] = new int[n] ;
        int suffix[] = new int[n];
     
        // To check whether a character
        // has appeared till ith index
        int seen[] = new int[26];
     
        // Calculating prefix array
        for (int i = 0; i < n; i++) {
     
            int prev = (i - 1 >= 0 ?
                prefix[i - 1] : 0);
     
            // Character appears for
            // the first time in string
            if (seen[s.charAt(i) - 'a'] == 0) {
                prefix[i] += (prev + 1);
            }
            else
                prefix[i] = prev;
     
            // Character is visited
            seen[s.charAt(i)- 'a'] = 1;
        }
         
        // Resetting seen for
        // suffix calculation
        for(int i = 0; i <26; i++)
            seen[i] = 0;
     
        // Calculating the suffix array
        suffix[n - 1] = 0;
        for (int i = n - 1; i >= 1; i--) {
            int prev = suffix[i];
     
            // Character appears
            // for the first time
            if (seen[s.charAt(i) - 'a'] == 0) {
                suffix[i - 1] += (prev + 1);
            }
            else
                suffix[i - 1] = prev;
     
            // This character
            // has now appeared
            seen[s.charAt(i)- 'a'] = 1;
        }
         
        // Loop to calculate the number
        // partition points in the string
        for (int i = 0; i < n; i++) {
  
            // Check whether number of
            // distinct characters are equal
            if (prefix[i] == suffix[i])
                answer++;
        }
        return answer;
    }
     
    // Driver Code
    public static void main (String[] args)
    {
        String s = "ababa";
     
        System.out.println(waysToSplit(s));
    }
 
}
 
// This code is contributed by Yash_R


Python3
# Python3 implementation to count the
# number of ways to partition the
# string such that each partition
# have same number of distinct
# characters in the string
 
# Function to count the number
# of ways to partition the string
# such that each partition have
# same number of distinct character
def waysToSplit(s) :
 
    n = len(s);
    answer = 0;
     
    # Prefix and suffix array for
    # distinct character from
    # start and end
    prefix = [ 0 ]*n;
    suffix = [0 ]*n;
 
    # To check whether a character
    # has appeared till ith index
    seen = [ 0 ]*26;
 
    # Calculating prefix array
    for i in range(n) :
 
        prev = prefix[i - 1] if (i - 1 >= 0 ) else  0;
 
        # Character appears for
        # the first time in string
        if (seen[ord(s[i]) - ord('a')] == 0) :
            prefix[i] += (prev + 1);
         
        else :
            prefix[i] = prev;
 
        # Character is visited
        seen[ord(s[i]) - ord('a')] = 1;
     
    # Resetting seen for
    # suffix calculation
    seen = [0]*len(seen);
 
    # Calculating the suffix array
    suffix[n - 1] = 0;
    for i in range(n - 1, 0, -1) :
        prev = suffix[i];
 
        # Character appears
        # for the first time
        if (seen[ord(s[i]) - ord('a')] == 0) :
            suffix[i - 1] += (prev + 1);
         
        else :
            suffix[i - 1] = prev;
 
        # This character
        # has now appeared
        seen[ord(s[i]) - ord('a')] = 1;
     
    # Loop to calculate the number
    # partition points in the string
    for i in range(n) :
        # Check whether number of
        # distinct characters are equal
        if (prefix[i] == suffix[i]) :
            answer += 1;
     
    return answer;
 
 
# Driver Code
if __name__ == "__main__" :
 
    s = "ababa";
 
    print(waysToSplit(s));
 
# This code is contributed by Yash_R


C#
// C# implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
using System;
 
public class GFG {
     
    // Function to count the number
    // of ways to partition the string
    // such that each partition have
    // same number of distinct character
    static int waysToSplit(string s)
    {
        int n = s.Length;
        int answer = 0;
         
        // Prefix and suffix array for
        // distinct character from
        // start and end
        int []prefix = new int[n] ;
        int []suffix = new int[n];
     
        // To check whether a character
        // has appeared till ith index
        int []seen = new int[26];
     
        // Calculating prefix array
        for (int i = 0; i < n; i++) {
     
            int prev = (i - 1 >= 0 ? prefix[i - 1] : 0);
     
            // Character appears for
            // the first time in string
            if (seen[s[i] - 'a'] == 0) {
                prefix[i] += (prev + 1);
            }
            else
                prefix[i] = prev;
     
            // Character is visited
            seen[s[i]- 'a'] = 1;
        }
         
        // Resetting seen for
        // suffix calculation
        for(int i = 0; i <26; i++)
            seen[i] = 0;
     
        // Calculating the suffix array
        suffix[n - 1] = 0;
        for (int i = n - 1; i >= 1; i--) {
            int prev = suffix[i];
     
            // Character appears
            // for the first time
            if (seen[s[i] - 'a'] == 0) {
                suffix[i - 1] += (prev + 1);
            }
            else
                suffix[i - 1] = prev;
     
            // This character
            // has now appeared
            seen[s[i]- 'a'] = 1;
        }
         
        // Loop to calculate the number
        // partition points in the string
        for (int i = 0; i < n; i++) {
  
            // Check whether number of
            // distinct characters are equal
            if (prefix[i] == suffix[i])
                answer++;
        }
        return answer;
    }
     
    // Driver Code
    public static void Main (string[] args)
    {
        string s = "ababa";
     
        Console.WriteLine(waysToSplit(s));
    }
 
}
 
// This code is contributed by Yash_R


Javascript


输出:
2

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

有效的方法:这个想法是在访问字符的哈希映射和从字符串的开始到当前索引的不同字符的前缀和后缀和数组的帮助下,为每个可能的子字符串预先计算不同的字符。下面是步骤的图示:

  • 遍历每个可能索引的字符串并计算从开始到该索引的不同字符的计数。
    • 如果第一次访问当前索引字符,则将来自前一个索引的不同字符的计数增加
if (visited[s[i]] == False)
    prefix[i] = prefix[i-1] + 1
  • 如果当前索引字符早些时候访问,然后从开始偏移量到当前指数字符迥异的计数将等于最后一个索引的不同字符。那是 –
if (visited[s[i]] == True)
    prefix[i] = prefix[i-1]
  • 最后,字符串的遍历和每个索引,每个分区字符串的不同字符数可以计算为 –
Count in left partitioned string 
    = prefix[i]

Count in right partitioned string
    = prefix[L] - prefix[i+1] 

下面是上述方法的实现:

C++

// C++ implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
 
#include 
 
using namespace std;
 
// Function to count the number
// of ways to partition the string
// such that each partition have
// same number of distinct character
int waysToSplit(string s)
{
    int n = s.length();
    int answer = 0;
     
    // Prefix and suffix array for
    // distinct character from
    // start and end
    int prefix[n] = { 0 };
    int suffix[n] = { 0 };
 
    // To check whether a character
    // has appeared till ith index
    int seen[26] = { 0 };
 
    // Calculating prefix array
    for (int i = 0; i < n; i++) {
 
        int prev = (i - 1 >= 0 ?
              prefix[i - 1] : 0);
 
        // Character appears for
        // the first time in string
        if (seen[s[i] - 'a'] == 0) {
            prefix[i] += (prev + 1);
        }
        else
            prefix[i] = prev;
 
        // Character is visited
        seen[s[i] - 'a'] = 1;
    }
     
    // Resetting seen for
    // suffix calculation
    memset(seen, 0, sizeof(seen));
 
    // Calculating the suffix array
    suffix[n - 1] = 0;
    for (int i = n - 1; i >= 1; i--) {
        int prev = suffix[i];
 
        // Character appears
        // for the first time
        if (seen[s[i] - 'a'] == 0) {
            suffix[i - 1] += (prev + 1);
        }
        else
            suffix[i - 1] = prev;
 
        // This character
        // has now appeared
        seen[s[i] - 'a'] = 1;
    }
     
    // Loop to calculate the number
    // partition points in the string
    for (int i = 0; i < n; i++) {
        // Check whether number of
        // distinct characters are equal
        if (prefix[i] == suffix[i])
            answer++;
    }
    return answer;
}
 
// Driver Code
int main()
{
    string s = "ababa";
 
    cout << waysToSplit(s);
    return 0;
}

Java

// Java implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
class GFG {
     
    // Function to count the number
    // of ways to partition the string
    // such that each partition have
    // same number of distinct character
    static int waysToSplit(String s)
    {
        int n = s.length();
        int answer = 0;
         
        // Prefix and suffix array for
        // distinct character from
        // start and end
        int prefix[] = new int[n] ;
        int suffix[] = new int[n];
     
        // To check whether a character
        // has appeared till ith index
        int seen[] = new int[26];
     
        // Calculating prefix array
        for (int i = 0; i < n; i++) {
     
            int prev = (i - 1 >= 0 ?
                prefix[i - 1] : 0);
     
            // Character appears for
            // the first time in string
            if (seen[s.charAt(i) - 'a'] == 0) {
                prefix[i] += (prev + 1);
            }
            else
                prefix[i] = prev;
     
            // Character is visited
            seen[s.charAt(i)- 'a'] = 1;
        }
         
        // Resetting seen for
        // suffix calculation
        for(int i = 0; i <26; i++)
            seen[i] = 0;
     
        // Calculating the suffix array
        suffix[n - 1] = 0;
        for (int i = n - 1; i >= 1; i--) {
            int prev = suffix[i];
     
            // Character appears
            // for the first time
            if (seen[s.charAt(i) - 'a'] == 0) {
                suffix[i - 1] += (prev + 1);
            }
            else
                suffix[i - 1] = prev;
     
            // This character
            // has now appeared
            seen[s.charAt(i)- 'a'] = 1;
        }
         
        // Loop to calculate the number
        // partition points in the string
        for (int i = 0; i < n; i++) {
  
            // Check whether number of
            // distinct characters are equal
            if (prefix[i] == suffix[i])
                answer++;
        }
        return answer;
    }
     
    // Driver Code
    public static void main (String[] args)
    {
        String s = "ababa";
     
        System.out.println(waysToSplit(s));
    }
 
}
 
// This code is contributed by Yash_R

蟒蛇3

# Python3 implementation to count the
# number of ways to partition the
# string such that each partition
# have same number of distinct
# characters in the string
 
# Function to count the number
# of ways to partition the string
# such that each partition have
# same number of distinct character
def waysToSplit(s) :
 
    n = len(s);
    answer = 0;
     
    # Prefix and suffix array for
    # distinct character from
    # start and end
    prefix = [ 0 ]*n;
    suffix = [0 ]*n;
 
    # To check whether a character
    # has appeared till ith index
    seen = [ 0 ]*26;
 
    # Calculating prefix array
    for i in range(n) :
 
        prev = prefix[i - 1] if (i - 1 >= 0 ) else  0;
 
        # Character appears for
        # the first time in string
        if (seen[ord(s[i]) - ord('a')] == 0) :
            prefix[i] += (prev + 1);
         
        else :
            prefix[i] = prev;
 
        # Character is visited
        seen[ord(s[i]) - ord('a')] = 1;
     
    # Resetting seen for
    # suffix calculation
    seen = [0]*len(seen);
 
    # Calculating the suffix array
    suffix[n - 1] = 0;
    for i in range(n - 1, 0, -1) :
        prev = suffix[i];
 
        # Character appears
        # for the first time
        if (seen[ord(s[i]) - ord('a')] == 0) :
            suffix[i - 1] += (prev + 1);
         
        else :
            suffix[i - 1] = prev;
 
        # This character
        # has now appeared
        seen[ord(s[i]) - ord('a')] = 1;
     
    # Loop to calculate the number
    # partition points in the string
    for i in range(n) :
        # Check whether number of
        # distinct characters are equal
        if (prefix[i] == suffix[i]) :
            answer += 1;
     
    return answer;
 
 
# Driver Code
if __name__ == "__main__" :
 
    s = "ababa";
 
    print(waysToSplit(s));
 
# This code is contributed by Yash_R

C#

// C# implementation to count the
// number of ways to partition the
// string such that each partition
// have same number of distinct
// characters in the string
using System;
 
public class GFG {
     
    // Function to count the number
    // of ways to partition the string
    // such that each partition have
    // same number of distinct character
    static int waysToSplit(string s)
    {
        int n = s.Length;
        int answer = 0;
         
        // Prefix and suffix array for
        // distinct character from
        // start and end
        int []prefix = new int[n] ;
        int []suffix = new int[n];
     
        // To check whether a character
        // has appeared till ith index
        int []seen = new int[26];
     
        // Calculating prefix array
        for (int i = 0; i < n; i++) {
     
            int prev = (i - 1 >= 0 ? prefix[i - 1] : 0);
     
            // Character appears for
            // the first time in string
            if (seen[s[i] - 'a'] == 0) {
                prefix[i] += (prev + 1);
            }
            else
                prefix[i] = prev;
     
            // Character is visited
            seen[s[i]- 'a'] = 1;
        }
         
        // Resetting seen for
        // suffix calculation
        for(int i = 0; i <26; i++)
            seen[i] = 0;
     
        // Calculating the suffix array
        suffix[n - 1] = 0;
        for (int i = n - 1; i >= 1; i--) {
            int prev = suffix[i];
     
            // Character appears
            // for the first time
            if (seen[s[i] - 'a'] == 0) {
                suffix[i - 1] += (prev + 1);
            }
            else
                suffix[i - 1] = prev;
     
            // This character
            // has now appeared
            seen[s[i]- 'a'] = 1;
        }
         
        // Loop to calculate the number
        // partition points in the string
        for (int i = 0; i < n; i++) {
  
            // Check whether number of
            // distinct characters are equal
            if (prefix[i] == suffix[i])
                answer++;
        }
        return answer;
    }
     
    // Driver Code
    public static void Main (string[] args)
    {
        string s = "ababa";
     
        Console.WriteLine(waysToSplit(s));
    }
 
}
 
// This code is contributed by Yash_R

Javascript


输出:
2

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程