Sum of indices of Characters removed to obtain an Empty String based on given conditions

Given a string str, consisting of lowercase English alphabets, the task is to calculate the sum of indices(1-based indexing) of the characters removed to obtain an empty string by the following operations:

  • Remove the smallest alphabet in the string.
  • For multiple occurrences of the smallest alphabet, remove the one present at the smallest index.
  • After removal of each character, the indices of all characters on its right reduces by 1.

Examples:

Input: str = “aba”
Output: 4
Explanation:aba” -> “ba”, Sum = 1
“ba” -> “b”, Sum = 1 + 2 = 3
“b” -> “”, Sum = 3 + 1 = 4

Input: str = “geeksforgeeks”
Output: 41

Naive Approach:
Follow the steps below to solve the problem:



  • Find the smallest character with minimum index.
  • Delete that character from string and shift all the characters one index to the right.
  • Repeat the above steps until the string is empty.

Time Complexity: O(N^2)
Auxiliary Space: O(N)

Efficient Approach: The above approach can be optimized using Segment Tree and Hashing. Follow the steps below to solve the problem:

  • It can be observed that only the indices on the right of the deleted charactr are affected, that is, they need to be shifted by one position.
  • Store the indices of the characters in a HashMap
  • Process the characters in the HashMap.
  • Find the number of elements which are left to the current index of the character, which are already deleted from the string, using Segment Tree.
  • Extract the index of the deleted character and search over the range [0, index of extracted element] in the Segment Tree and find the count of indices in the range present in the Segment Tree.
  • Add index of extracted element – count to the answer and insert the index of the currently deleted element into the Segment Tree.
  • Repeat the above steps until the string is empty.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to add index of the deleted character
void add_seg(int seg[], int start, int end, int current,
             int index)
{
  
    // If index is beyond the range
    if (index > end or index < start)
        return;
  
    // Insert the index of the deleted
    // characeter
    if (start == end) {
        seg[current] = 1;
        return;
    }
    int mid = (start + end) / 2;
  
    // Search over the subtrees to find the
    // desired index
    add_seg(seg, start, mid, 2 * current + 1, index);
    add_seg(seg, mid + 1, end, 2 * current + 2, index);
    seg[current]
        = seg[2 * current + 1] + seg[2 * current + 2];
}
  
// Function to return count of deleted indices
// which are to the left of the current index
int deleted(int seg[], int l, int r, int start, int end,
            int current)
{
    if (end < l or start > r)
        return 0;
    if (start >= l and end <= r)
        return seg[current];
    int mid = (start + end) / 2;
    return deleted(seg, l, r, start, mid, 2 * current + 1)
           + deleted(seg, l, r, mid + 1, end,
                     2 * current + 2);
}
  
// Function to generate the 
// sum of indices 
void sumOfIndices(string s)
{
    int N = s.size();
    int x = int(ceil(log2(N)));
    int seg_size = 2 * (int)pow(2, x) - 1;
    int segment[seg_size] = { 0 };
  
    int count = 0;
  
    // Stores the original index of the
    // characters in sorted order of key
    map<int, queue<int> > fre;
    for (int i = 0; i < N; i++) {
        fre[s[i]].push(i);
    }
  
    // Traverse the map
    while (fre.empty() == false) {
  
        // Extract smallest index
        // of smallest characetr
        auto it = fre.begin();
  
        // Delete the character from the map
        // if it has no remaining occurrence
        if (it->second.empty() == true)
            fre.erase(it->first);
        else {
  
            // Stores the original index
            int original_index
                = it->second.front();
  
            // Count of elements removed to
            // the left of current character
            int curr_index
                = deleted(segment, 0, original_index - 1,
                          0, N - 1, 0);
  
            // Current index of the current character
            int new_index
                = original_index - curr_index;
  
            // For 1-based indexing
            count += new_index + 1;
  
            // Insert the deleted index
            // in the segment tree
            add_seg(segment, 0, N - 1,
                    0, original_index);
            it->second.pop();
        }
    }
  
    // Final answer
    cout << count << endl;
}
  
// Driver Code
int main()
{
    string s = "geeksforgeeks";
    sumOfIndices(s);
}

chevron_right


Output:

41

Time Complexity: O(N log N)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Recommended Posts:


Competitive Programming enthusiast 4 star at codechef 5 star at Hackerrank love to solve problems

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.