Similar String Groups in C++

C++Server Side ProgrammingProgramming

Suppose we have two strings X and Y, these are similar if we can swap two letters of X, so that it equals Y. Also two the strings X and Y are similar if they are equal. As an example, consider, two strings are like "tars" and "rats" are similar, if we swap t and r, then we can find another, now "rats" and "arts" are similar, but "star" is not similar to "tars", "rats", or "arts". Now we can see, these form two connected groups by similarity: {"tars", "rats", "arts"} and {"star"}. Here "tars" and "arts" are in the same group even though they are not similar. So, each group is such that a word is in the group if and only if it is similar to at least one other word in the group. Suppose we have a list A of strings. Every string in A is an anagram of every other string in A. We have to find how many groups are there?

So, if the input is like ["tars","rats","arts","star"], then the output will be 2

To solve this, we will follow these steps −

  • Define an array parent

  • Define an array rank

  • Define a function getParent(), this will take x,

    • if parent[x] is same as -1, then −

      • return x

    • return parent[x] = getParent(parent[x])

  • Define a function unionn(), this will take x, y,

    • parX := getParent(x), parY := getParent(y)

    • if parX is same as parY, then −

      • return false

    • if rank[parX] >= rank[parY], then −

      • rank[parX] := rank[parX] + rank[parY]

      • parent[parY] := parX

    • Otherwise

      • rank[parY] := rank[parY] + rank[parX]

      • parent[parX] := parY

    • return true

  • Define a function ok(), this will take s1, s2,

    • cnt := 0

    • for initialize i := 0, when i < size of s1, update (increase i by 1), do −

      • if s1[i] is not equal to s2[i], then −

        • (increase cnt by 1)

      • if cnt > 2, then −

        • return false

    • return true

  • From the main method, do the following −

  • ret := 0

  • n := size of A

  • ret := n

  • parent := an array of size n, and fill this with -1

  • rank := an array of size n, and fill this with 1

  • for initialize i := 0, when i < n, update (increase i by 1), do −

    • for initialize j := i + 1, when j < n, update (increase j by 1), do −

      • if ok(A[i], A[j]) is non-zero, then −

        • if unionn(i, j) is non-zero, then −

          • (decrease ret by 1)

  • return ret

Let us see the following implementation to get better understanding −

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
      cout << v[i] << ", ";
   }
   cout << "]"<<endl;
}
class Solution {
   public:
   vector<int> parent;
   vector<int> rank;
   int getParent(int x){
      if (parent[x] == -1)
      return x;
      return parent[x] = getParent(parent[x]);
   }
   bool unionn(int x, int y){
      int parX = getParent(x);
      int parY = getParent(y);
      if (parX == parY)
      return false;
      if (rank[parX] >= rank[parY]) {
         rank[parX] += rank[parY];
         parent[parY] = parX;
      } else {
         rank[parY] += rank[parX];
         parent[parX] = parY;
      }
      return true;
   }
   bool ok(string& s1, string& s2){
      int cnt = 0;
      for (int i = 0; i < s1.size(); i++) {
         if (s1[i] != s2[i])
         cnt++;
         if (cnt > 2)
         return false;
      }
      return true;
   }
   int numSimilarGroups(vector<string>& A){
      int ret = 0;
      int n = A.size();
      ret = n;
      parent = vector<int>(n, -1);
      rank = vector<int>(n, 1);
      for (int i = 0; i < n; i++) {
         for (int j = i + 1; j < n; j++) {
            if (ok(A[i], A[j])) {
               if (unionn(i, j))
               ret--;
            }
         }
      }
      return ret;
   }
};
main(){
   Solution ob;
   vector<string> v = {"tars","rats","arts","star"};
   cout << (ob.numSimilarGroups(v));
}

Input

{"tars","rats","arts","star"}

Output

2
raja
Published on 04-Jun-2020 08:16:10
Advertisements