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

📅  最后修改于: 2021-04-25 00:42:49             🧑  作者: 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


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


输出:
2

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

有效的方法:我们的想法是预先计算的鲜明字符与哈希地图的帮助访问字符和前缀和后缀和阵列从开始的不同字符字符串的当前索引每个可能的子字符串。下面是步骤说明:

  • 遍历每个可能的索引的字符串,并计算从开始到该索引的不同字符数。
    • 如果是第一次访问当前索引字符,则将上一个索引中不同字符的计数增加1。
      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

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
输出:
2

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