Word Squares in C++


Suppose we have a set of words (all are unique), we have to find all word squares and we can build from them. Here a sequence of words forms a valid word square if the kth row and column read the exact same string, where 0 ≤ k < maximum of numRows and numColumns. So as an example, the word sequence ["ball","area","lead","lady"] will construct a word square because each word reads the same both horizontally and vertically.

ball
area
lead
lady

So, if the input is like ["area","lead","wall","lady","ball"], then the output will be [[ "wall", "area", "lead", "lady"], ["ball", "area", "lead", "lady"]]

To solve this, we will follow these steps −

  • Define a node structure, there will be a variable isEnd and a list of child nodes

  • Define one 2D array ret

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

  • node := head

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

    • x := s[i]

    • if child array of node is empty, then −

      • child[x] of node := new node

    • node := child[x] of node

  • isEnd of node := true

  • Define a function called getAllWords, this will take idx, prefixm node and temp array

  • if node is empty, then −

    • return

  • if isEnd of node is true, then −

    • insert curr at the end of temp

    • return

  • if idx >= size of prefix, then −

    • for each node it in child of node −

      • getAllWords(idx, prefix, it.second, temp, curr + it.first)

  • Otherwise −

    • x := prefix[idx]

    • if child of node is not empty, then −

      • return

    • getAllWords(idx + 1, prefix, child[x] of node, temp, curr + x)

  • Define a function solve(), this will take an array temp, idx, reqSize, head,

  • if idx is same as reqSize, then −

    • insert temp at the end of ret

    • return

  • prefix := empty string

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

    • prefix := prefix + temp[i, idx]

  • Define an array possible

  • curr = head

  • getAllWords(0, prefix, curr, possible)

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

    • s := possible[i]

    • insert s at the end of temp

    • solve(temp, idx + 1, reqSize, head)

    • delete last element from temp

  • From the main method do the following −

  • head = new node

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

    • insertNode(head, words[i])

  • Define an array temp

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

    • s := words[i]

    • insert s at the end of temp

    • solve(temp, 1, size of words[0], head)

    • delete last element from temp

  • return ret

Example 

Let us see the following implementation to get a better understanding −

 Live Demo

#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<vector<auto>> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
      cout << "[";
      for(int j = 0; j <v[i].size(); j++){
         cout << v[i][j] << ", ";
      }
      cout << "],";
   }
   cout << "]"<<endl;
}
struct Node {
   bool isEnd;
   map<char, Node *> child;
};
class Solution {
public:
   vector<vector<string>> ret;
   void insertNode(Node *head, string &s) {
      Node *node = head;
      for (int i = 0; i < s.size(); i++) {
         char x = s[i];
         if (!node->child[x]) {
            node->child[x] = new Node();
         }
         node = node->child[x];
      }
      node->isEnd = true;
   }
   void getAllWords(int idx, string prefix, Node *node, vector<string>&temp,
      string curr = "") {
         if (!node)
            return;
         if (node->isEnd) {
            temp.push_back(curr);
            return;
         }
         if (idx >= prefix.size()) {
            for (auto &it : node->child) {
               getAllWords(idx, prefix, it.second, temp, curr + it.first);
            }
         }
         else {
            char x = prefix[idx];
            if (!node->child[x])
               return;
            getAllWords(idx + 1, prefix, node->child[x], temp, curr + x);
         }
   }
   void solve(vector<string> &temp, int idx, int reqSize, Node *head){
      if (idx == reqSize) {
         ret.push_back(temp);
         return;
      }
      string prefix = "";
      for (int i = 0; i < temp.size(); i++) {
         prefix += temp[i][idx];
      }
      vector<string> possible;
      Node *curr = head;
      getAllWords(0, prefix, curr, possible);
      for (int i = 0; i < possible.size(); i++) {
         string s = possible[i];
         temp.push_back(s);
         solve(temp, idx + 1, reqSize, head);
         temp.pop_back();
      }
   }
   vector<vector<string>> wordSquares(vector<string> &words) {
      ret.clear();
      Node *head = new Node();
      for (int i = 0; i < words.size(); i++) {
         insertNode(head, words[i]);
      }
      vector<string> temp;
      for (int i = 0; i < words.size(); i++) {
         string s = words[i];
         temp.push_back(s);
         solve(temp, 1, (int)words[0].size(), head);
         temp.pop_back();
      }
      return ret;
   }
};
main() {
   Solution ob;
   vector<string> v = {"area", "lead", "wall", "lady", "ball"};
   print_vector(ob.wordSquares(v));
}

Input

{"area", "lead", "wall", "lady", "ball"}

Output

[[wall, area, lead, lady, ],[ball, area, lead, lady, ],]

Updated on: 21-Jul-2020

211 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements