Open In App

Number of pairs of String whose concatenation leads to a Sorted string

Last Updated : 04 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of strings S with the size of N where each string contains at least two distinct characters. The task is to find the number of pairs of strings ( s[i], s[j] ) whose concatenation forms a string that is alphabetically sorted. Here concatenation is simply the process of appending one string after another.

Examples:

Input: S[] = {“aax”, “bbc”, “xz”}
Output: 2
Explanation:  The pairs that form a sorted string when concatenated are: {“aax”, “xz”}, {“bbc”, “xz”}

Input: S[] = {“fg”, “mt”, “cd”}
Output: 3
Explanation: The pairs that form a sorted string when concatenated are: {“cd”, “fg”}, {“cd”, “mt”}, {“fg”, “mt”}

Naive Approach: The basic way to solve the problem is:

The brute force approach for this problem is to concatenate every pair of strings and then find out if the string formed is sorted or not. 

Time complexity: O(N*N*max_size) where N is the size of the array of strings and max_size is the maximum size of the concatenation of two strings.
Auxiliary Space: O(1)

Efficient Approach: A better solution is based on these facts:

  • If a string s1 is already unsorted and s2 is any random string then s1 + s2 will not form a sorted string.
  • If the last character of a string s1 is lesser than or equal to the first character of another string s2 only then the string s1 + s2 can be sorted (provided both s1 and s2 are sorted).

Follow the below-mentioned steps to implement the above approach:

  • Initialize a boolean array mark[] and label only those indexes as 1 for which s[i] is sorted and all other indexes as 0 (as to not consider them later).
  • For each alphabet (a-z), calculate the number of sorted strings( mark[i] =1 ) that start with that particular alphabet and store the count in another array ( say nums ).
  • For each string s[i], store the last character of that string in some last_char variable. A string that starts with an alphabet that comes after or equal to last_char can get appended to s[i] and it will always form a sorted string.
  • Now iterate from the last_char till the last alphabet i.e. z and increment ans variable by the number of strings starting from each character involved in iteration.
  • Return the answer.

Below is the implementation of the above approach:

C++




// C++ implementation of program
#include <bits/stdc++.h>
using namespace std;
 
// Check if a particular string is
// sorted or not
bool sorted(string s)
{
 
    for (int i = 0; i < s.size() - 1; i++) {
        if (s[i] > s[i + 1])
            return false;
    }
    return 1;
}
 
// Function to find the required
// number of pairs
int solve(string S[], int N)
{
 
    // Boolean array mark to consider only
    // those strings which are sorted and
    // reject those which are not sorted
    bool mark[N + 1] = { 0 };
 
    for (int i = 0; i < N; i++) {
        if (sorted(S[i])) {
            mark[i] = 1;
        }
    }
    // For every lower_case alphabet find out
    // how many strings start with that
    // particular alphabet
    int nums[26] = { 0 };
 
    for (int i = 0; i < N; i++) {
 
        if (mark[i] == 1) {
            int p = S[i][0] - 'a';
            nums[p] += 1;
        }
    }
 
    // Compute the answer for all
    // the sorted strings
    int ans = 0;
    for (int i = 0; i < N; i++) {
        if (mark[i] == 1) {
            int len = S[i].size();
            int last_char = S[i][len - 1] - 'a';
 
            for (int j = last_char; j < 26; j++) {
                ans += nums[j];
            }
        }
    }
 
    // Return the answer
    return ans;
}
 
// Driver Code
int main()
{
 
    // Test case 1
    string S[] = { "ac", "df", "pzz" };
    int N = sizeof(S) / sizeof(S[0]);
 
    // Function call
    cout << solve(S, N) << endl;
 
    // Test case 2
    string S2[] = { "pqrs", "amq", "bcd" };
    N = sizeof(S2) / sizeof(S2[0]);
 
    // Function call
    cout << solve(S2, N) << endl;
    return 0;
}


Java




// Java code for the above approach
import java.util.Arrays;
 
public class Main {
 
    // Check if a particular string is
    // sorted or not
    static boolean sorted(String s)
    {
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.charAt(i) > s.charAt(i + 1)) {
                return false;
            }
        }
        return true;
    }
 
    // Function to find the required
    // number of pairs
    static int solve(String[] S, int N)
    {
        // Boolean array mark to consider only
        // those strings which are sorted and
        // reject those which are not sorted
        boolean[] mark = new boolean[N + 1];
        Arrays.fill(mark, false);
 
        for (int i = 0; i < N; i++) {
            if (sorted(S[i])) {
                mark[i] = true;
            }
        }
        // For every lower_case alphabet find out
        // how many strings start with that
        // particular alphabet
        int[] nums = new int[26];
        Arrays.fill(nums, 0);
 
        for (int i = 0; i < N; i++) {
            if (mark[i]) {
                int p = S[i].charAt(0) - 'a';
                nums[p] += 1;
            }
        }
 
        // Compute the answer for all
        // the sorted strings
        int ans = 0;
        for (int i = 0; i < N; i++) {
            if (mark[i]) {
                int len = S[i].length();
                int lastChar = S[i].charAt(len - 1) - 'a';
 
                for (int j = lastChar; j < 26; j++) {
                    ans += nums[j];
                }
            }
        }
 
        // Return the answer
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        // Test case 1
        String[] S = { "ac", "df", "pzz" };
        int N = S.length;
 
        // Function call
        System.out.println(solve(S, N));
 
        // Test case 2
        String[] S2 = { "pqrs", "amq", "bcd" };
        N = S2.length;
 
        // Function call
        System.out.println(solve(S2, N));
    }
}
// This code is contributed by Potta Lokesh


Python3




# Python code for the above approach
 
# Check if a particular string is
# sorted or not
def sorted(s):
    for i in range(len(s) - 1):
        if s[i] > s[i + 1]:
            return False
    return True
 
# Function to find the required
# number of pairs
def solve(S, N):
    # Boolean array mark to consider only
    # those strings which are sorted and
    # reject those which are not sorted
    mark = [False] * (N + 1)
    for i in range(N):
        if sorted(S[i]):
            mark[i] = True
 
    # For every lower_case alphabet find out
    # how many strings start with that
    # particular alphabet
    nums = [0] * 26
    for i in range(N):
        if mark[i]:
            p = ord(S[i][0]) - ord('a')
            nums[p] += 1
 
    # Compute the answer for all
    # the sorted strings
    ans = 0
    for i in range(N):
        if mark[i]:
            Len = len(S[i])
            lastChar = ord(S[i][Len - 1]) - ord('a')
            for j in range(lastChar, 26):
                ans += nums[j]
    # return the answer
    return ans
 
 
# Test case 1
S = ["ac", "df", "pzz"]
N = len(S)
 
# Function call
print(solve(S, N))
 
# Test case 2
S2 = ["pqrs", "amq", "bcd"]
N = len(S2)
 
# Function call
print(solve(S2, N))
 
# This code is contributed by lokeshmvs21.


C#




// C# code for the above approach
using System;
 
public class GFG {
 
  // Check if a particular string is
  // sorted or not
  static bool sorted(string s)
  {
    for (int i = 0; i < s.Length - 1; i++) {
      if (s[i] > s[i + 1]) {
        return false;
      }
    }
    return true;
  }
 
  // Function to find the required
  // number of pairs
  static int solve(string[] S, int N)
  {
    // Boolean array mark to consider only
    // those strings which are sorted and
    // reject those which are not sorted
    bool[] mark = new bool[N + 1];
    for (int i = 0; i < N + 1; i++) {
      mark[i] = false;
    }
 
    for (int i = 0; i < N; i++) {
      if (sorted(S[i])) {
        mark[i] = true;
      }
    }
    // For every lower_case alphabet find out
    // how many strings start with that
    // particular alphabet
    int[] nums = new int[26];
    for (int i = 0; i < 26; i++) {
      nums[i] = 0;
    }
 
    for (int i = 0; i < N; i++) {
      if (mark[i]) {
        int p = (int)S[i][0] - (int)'a';
        nums[p] += 1;
      }
    }
 
    // Compute the answer for all
    // the sorted strings
    int ans = 0;
    for (int i = 0; i < N; i++) {
      if (mark[i]) {
        int len = S[i].Length;
        int lastChar
          = (int)S[i][len - 1] - (int)'a';
 
        for (int j = lastChar; j < 26; j++) {
          ans += nums[j];
        }
      }
    }
 
    // Return the answer
    return ans;
  }
 
  static public void Main()
  {
 
    // Code
    // Test case 1
    string[] S = { "ac", "df", "pzz" };
    int N = S.Length;
 
    // Function call
    Console.WriteLine(solve(S, N));
 
    // Test case 2
    string[] S2 = { "pqrs", "amq", "bcd" };
    N = S2.Length;
 
    // Function call
    Console.WriteLine(solve(S2, N));
  }
}
 
// This code is contributed by lokesh.


Javascript




// Check if a particular string is
// sorted or not
function sorted(s) {
  for (let i = 0; i < s.length - 1; i++) {
    if (s[i] > s[i + 1]) return false;
  }
  return true;
}
 
// Function to find the required
// number of pairs
function solve(S, N) {
   // Boolean array mark to consider only
    // those strings which are sorted and
    // reject those which are not sorted
  const mark = new Array(N + 1).fill(false);
  for (let i = 0; i < N; i++) {
    if (sorted(S[i])) {
      mark[i] = true;
    }
  }
  // For every lower_case alphabet find out
    // how many strings start with that
    // particular alphabet
  const nums = new Array(26).fill(0);
  for (let i = 0; i < N; i++) {
    if (mark[i]) {
      const p = S[i][0].charCodeAt(0) - 'a'.charCodeAt(0);
      nums[p] += 1;
    }
  }
  // Compute the answer for all the sorted strings.
  let ans = 0;
  for (let i = 0; i < N; i++) {
    if (mark[i]) {
      const len = S[i].length;
      const lastChar = S[i][len - 1].charCodeAt(0) - 'a'.charCodeAt(0);
      for (let j = lastChar; j < 26; j++) {
        ans += nums[j];
      }
    }
  }
  // Return the answer.
  return ans;
}
 
 // Test case 1
 let S = [ "ac", "df", "pzz" ];
 let N = S.length;
 
 // Function call
 console.log(solve(S, N));
 
 // Test case 2
 let S2 = [ "pqrs", "amq", "bcd" ];
 N = S2.length;
 
 // Function call
 console.log(solve(S2, N));
 
//  This code is contributed by akashish__


Output

3
1

Time Complexity: O(N*MAX_SIZE), MAX_SIZE is the length of longest string
Auxiliary Space: O(N)

Related Articles: 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads