Word Abbreviation in C++


Suppose we have an array of n unique strings, We have to generate minimal possible abbreviations for every word following rules below.

  • Starting with the first character and then the number of characters abbreviated, which followed by the last character.

  • If we find any conflict and that is more than one words share the same abbreviation, a longer prefix can be used instead of only the first character until making the map from word to abbreviation become unique.

  • When the abbreviation doesn't make the word shorter, then keep it as original.

So, if the input is like ["like", "god", "internal", "me", "internet", "interval", "intension", "face", "intrusion"], then the output will be

["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"]

To solve this, we will follow these steps −

  • Define a node structure, it has cnt and an array of 26 child nodes, initially all are empty.

  • Define a function freeNode(), this will take head,

  • if head null, then −

    • return

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

    • freeNode(child[i] of head)

  • delete head

  • Define a function insertNode(), this will take node, s,

  • curr = node

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

    • x := s[i]

    • if child[x - 'a'] of node is not null, then

      • child[x - 'a'] of node := a new node

    • node := child[x - 'a'] of node

    • increase cnt of node by 1

  • Define a function abbreviate(), this will take node, s,

  • ret := blank string

  • curr = node

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

    • x := s[i]

    • curr := child[x - 'a'] of curr

    • if cnt of curr is same as 1, then −

      • rem := size of s

      • ret := (if rem <= 1, then s, otherwise substring of s from index 0 to i concatenate rem as string concatenate last element of s

      • Come out from the loop

  • return ret

  • Define a function wordsAbbreviation(), this will take an array dict,

  • n := size of dict

  • Define an array ret of size n

  • Define one mapm

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

    • word := dict[i]

    • rem := size of word - 2

    • x := (if rem <= 1, then word, otherwise first element of word concatenate rem concatenate last element of word)

    • insert i at the end of m[x]

    • ret[i] := x

  • for each key-value pair it in m, do −

    • if size of value of it is <= 1, then −

      • (increase it by 1)

      • Ignore following part, skip to the next iteration

    • head := a new node

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

      • idx := value[i] of it

      • insertNode(head, dict[idx])

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

      • idx := value[i] of it

      • ret[idx] := abbreviate(head, dict[idx])

    • freeNode(head)

    • (increase it 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;
}
struct Node{
   int cnt;
   Node* child[26];
   Node(){
      cnt = 0;
      for(int i = 0; i < 26; i++)child[i] = NULL;
   }
};
class Solution {
   public:
   void freeNode(Node* head){
      if (!head)
      return;
      for (int i = 0; i < 26; i++) {
         freeNode(head->child[i]);
      }
      delete head;
   }
   void insertNode(Node* node, string s){
      Node* curr = node;
      for (int i = 0; i < s.size(); i++) {
         char x = s[i];
         if (!node->child[x - 'a']) {
            node->child[x - 'a'] = new Node();
         }
         node = node->child[x - 'a'];
         node->cnt++;
      }
   }
   string abbreviate(Node* node, string s){
      string ret = "";
      Node* curr = node;
      for (int i = 0; i < s.size(); i++) {
         char x = s[i];
         curr = curr->child[x - 'a'];
         if (curr->cnt == 1) {
            int rem = s.size() - (i + 2);
            ret = rem <= 1 ? s : s.substr(0, i + 1) + to_string(rem) + s.back();
            break;
         }
      }
      return ret;
   }
   vector<string> wordsAbbreviation(vector<string>& dict) {
      int n = dict.size();
      vector<string> ret(n);
      map<string, vector<int> > m;
      for (int i = 0; i < n; i++) {
         string word = dict[i];
         int rem = word.size() - 2;
         string x = rem <= 1 ? word : word.front() + to_string(rem) + word.back();
         m[x].push_back(i);
         ret[i] = x;
      }
      Node* head;
      map<string, vector<int> >::iterator it = m.begin();
      while (it != m.end()) {
         if (it->second.size() <= 1) {
            it++;
            continue;
         }
         head = new Node();
         for (int i = 0; i < it->second.size(); i++) {
            int idx = it->second[i];
            insertNode(head, dict[idx]);
         }
         for (int i = 0; i < it->second.size(); i++) {
            int idx = it->second[i];
            ret[idx] = abbreviate(head, dict[idx]);
         }
         freeNode(head);
         it++;
      }
      return ret;
   }
};
main(){
   Solution ob;
   vector<string> v =    {"like","god","internal","me","internet","interval","intension","face","intrusion"};
   print_vector(ob.wordsAbbreviation(v));
}

Input

{"like","god","internal","me","internet","interval","intension","face","intrusion"}

Output

[l2e, god, internal, me, i6t, interval, inte4n, f2e, intr4n, ]

Updated on: 11-Jul-2020

643 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements