📌  相关文章
📜  通过Q查询的给定范围对子字符串中的不同字符进行计数

📅  最后修改于: 2021-04-27 17:23:03             🧑  作者: Mango

给定一个字符串S ,该字符串S由大小为NQ的小写字母组成,范围为[L,R] ,则任务是为每个查询按给定范围打印子字符串中不同字符的计数。

例子:

天真的方法:想法是使用散列来维持给定子字符串中每个字符的频率,然后以等于1的频率对字符进行计数。

下面是上述方法的实现:

C++
// C++ Program for Naive Approach
  
#include 
using namespace std;
  
void findCount(string s, int L, int R)
{
    // counter to count distinct char
    int distinct = 0;
  
    // Initializing frequency array to
    // count characters as the appear in
    // substring S[L:R]
    int frequency[26] = {};
  
    // Iterating over S[L] to S[R]
    for (int i = L; i <= R; i++) {
  
        // incrementing the count
        // of s[i] character in frequency array
        frequency[s[i] - 'a']++;
    }
  
    for (int i = 0; i < 26; i++) {
  
        // if frequency of any character is > 0
        // then increment the counter
        if (frequency[i] > 0)
            distinct++;
    }
  
    cout << distinct << endl;
}
  
/* Driver code*/
int main()
{
    string s = "geeksforgeeksisacomputerscienceportal";
    int queries = 3;
    int Q[queries][2] = { { 0, 10 },
                          { 15, 18 },
                          { 12, 20 } };
  
    for (int i = 0; i < queries; i++)
        findCount(s, Q[i][0], Q[i][1]);
  
    return 0;
}


Java
// Java program for the naive approach
class GFG{
  
static void findCount(String s, int L,
                                int R)
{
      
    // Counter to count distinct char
    int distinct = 0;
  
    // Initializing frequency array 
    // to count characters as the 
    // appear in subString S[L:R]
    int []frequency = new int[26];
  
    // Iterating over S[L] to S[R]
    for(int i = L; i <= R; i++)
    {
         
       // Incrementing the count of s[i]
       // character in frequency array
       frequency[s.charAt(i) - 'a']++;
    }
  
    for(int i = 0; i < 26; i++)
    {
         
       // If frequency of any character 
       // is > 0 then increment the counter
       if (frequency[i] > 0)
           distinct++;
    }
    System.out.print(distinct + "\n");
}
  
// Driver code
public static void main(String[] args)
{
    String s = "geeksforgeeksisa" + 
               "computerscienceportal";
    int queries = 3;
    int Q[][] = { { 0, 10 },
                  { 15, 18 },
                  { 12, 20 } };
  
    for(int i = 0; i < queries; i++)
       findCount(s, Q[i][0], Q[i][1]);
}
}
  
// This code is contributed by sapnasingh4991


Python3
# Python3 program for Naive Approach
  
def findCount(s, L, R):
      
    # Counter to count distinct char
    distinct = 0
  
    # Initializing frequency array to
    # count characters as the appear in
    # substring S[L:R]
    frequency = [0 for i in range(26)]
  
    # Iterating over S[L] to S[R]
    for i in range(L, R + 1, 1):
          
        # Incrementing the count of s[i]
        # character in frequency array
        frequency[ord(s[i]) - ord('a')] += 1
  
    for i in range(26):
          
        # If frequency of any character is > 0
        # then increment the counter
        if (frequency[i] > 0):
            distinct += 1
  
    print(distinct)
  
# Driver code
if __name__ == '__main__':
      
    s = "geeksforgeeksisacomputerscienceportal"
    queries = 3
    Q = [ [ 0, 10 ],
          [ 15, 18 ],
          [ 12, 20 ] ]
  
    for i in range(queries):
        findCount(s, Q[i][0], Q[i][1])
  
# This code is contributed by Bhupendra_Singh


C#
// C# program for the naive approach
using System;
class GFG{
  
static void findCount(String s, int L,
                                int R)
{
      
    // Counter to count distinct char
    int distinct = 0;
  
    // Initializing frequency array 
    // to count characters as the 
    // appear in subString S[L:R]
    int []frequency = new int[26];
  
    // Iterating over S[L] to S[R]
    for(int i = L; i <= R; i++)
    {
          
        // Incrementing the count of s[i]
        // character in frequency array
        frequency[s[i] - 'a']++;
    }
  
    for(int i = 0; i < 26; i++)
    {
              
        // If frequency of any character 
        // is > 0 then increment the counter
        if (frequency[i] > 0)
            distinct++;
    }
    Console.Write(distinct + "\n");
}
  
// Driver code
public static void Main(String[] args)
{
    String s = "geeksforgeeksisa" + 
               "computerscienceportal";
    int queries = 3;
    int [,]Q = {{ 0, 10 },
                { 15, 18 },
                { 12, 20 }};
  
    for(int i = 0; i < queries; i++)
    findCount(s, Q[i, 0], Q[i, 1]);
}
}
  
// This code is contributed by sapnasingh4991


C++
// C++ Program for Efficient Approach
// to count the no. of distinct characters
// in a substring using STL
  
#include 
using namespace std;
  
// vector of vector to store
// position of all characters
// as they appear in string
vector > v(26);
  
void build_position_vector(string s)
{
    for (int i = 0; i < s.size(); i++) {
  
        // inserting position of
        // character as they appear
        v[s[i] - 'a'].push_back(i);
    }
}
  
void findCount(string s, int L, int R)
{
  
    build_position_vector(s);
  
    // counter to count distinct char
    int distinct = 0;
  
    // iterating over all 26 characters
    for (int i = 0; i < 26; i++) {
  
        // Finding the first element
        // which is greater than or equal to L
        auto first = lower_bound(
            v[i].begin(),
            v[i].end(), L);
  
        // Check if first pointer exists
        // and is less than or equal to R
        if (first != v[i].end()
            && *first <= R) {
            distinct++;
        }
    }
  
    cout << distinct << endl;
}
  
/* Driver code*/
int main()
{
    string s = "geeksforgeeksisacomputerscienceportal";
    int queries = 3;
    int Q[queries][2] = { { 0, 10 },
                          { 15, 18 },
                          { 12, 20 } };
  
    for (int i = 0; i < queries; i++)
        findCount(s, Q[i][0], Q[i][1]);
  
    return 0;
}


输出:
7
4
8

时间复杂度: O(Q×N)

高效的方法:一种有效的方法是将每个字符的位置存储在数组中的字符串中。对于每个给定的查询,我们将迭代所有26个小写字母。如果当前字母在子字符串S [L:R]中,则对应位置矢量中第一个大于或等于L的元素应存在且小于或等于R,即,必须在L和R之间存在一个位置值R表示查询范围内是否存在字母。

例如:

下面是上述方法的实现:

C++

// C++ Program for Efficient Approach
// to count the no. of distinct characters
// in a substring using STL
  
#include 
using namespace std;
  
// vector of vector to store
// position of all characters
// as they appear in string
vector > v(26);
  
void build_position_vector(string s)
{
    for (int i = 0; i < s.size(); i++) {
  
        // inserting position of
        // character as they appear
        v[s[i] - 'a'].push_back(i);
    }
}
  
void findCount(string s, int L, int R)
{
  
    build_position_vector(s);
  
    // counter to count distinct char
    int distinct = 0;
  
    // iterating over all 26 characters
    for (int i = 0; i < 26; i++) {
  
        // Finding the first element
        // which is greater than or equal to L
        auto first = lower_bound(
            v[i].begin(),
            v[i].end(), L);
  
        // Check if first pointer exists
        // and is less than or equal to R
        if (first != v[i].end()
            && *first <= R) {
            distinct++;
        }
    }
  
    cout << distinct << endl;
}
  
/* Driver code*/
int main()
{
    string s = "geeksforgeeksisacomputerscienceportal";
    int queries = 3;
    int Q[queries][2] = { { 0, 10 },
                          { 15, 18 },
                          { 12, 20 } };
  
    for (int i = 0; i < queries; i++)
        findCount(s, Q[i][0], Q[i][1]);
  
    return 0;
}
输出:
7
4
8

时间复杂度: O(N + Q logN)