Skip to content

Conversation

@altay9
Copy link
Collaborator

@altay9 altay9 commented Jul 18, 2021

Resolves: #220

425_valid_word_square

A word square matrix is naturally a symmetric matrix.
It means when we try the candidate words starting from the top row to the bottom row, the symmetric order will occur eventually, like in the above picture.
Therefore, we can interpret this situation as a constraint, and a constraint is nothing but a guide to pruning a solution tree.
As this question asks for all possible solutions to construct a word square and there occurs a constraint that helps us prune the tree, a kind of backtracking technique inevitably comes to mind.

In each insertion of the candidate words into the matrix, a prefix (which is the constraint at the same time) is built naturally.
Like in the picture:

  • When we insert ball into the matrix as the first candidate, we are obliged to insert a word starting with the prefix a into the second row.
  • After we insert the only suitable word "area", we are obliged to insert a word starting with the prefix le into the third row.

We could use a HashMap kind of data structure to store and retrieve the list of the words starting with the prefix needed.
We would use the prefix as a key, and the list of the words as the value.

But when we mention prefix and re(trie)ve, a Trie (prefix tree) data structure might be the perfect match.

The solution in the code is the fastest one on LeetCode. I just modularized and cleaned it to make it more readable.
Although the code is quite brilliant, there are some parts that disturb me.

For example, we need to fill an array with the same prefix tree to prune the root after each step. Sure, it helps to fasten the search on the tree, but there might be a leaner way about memory.

But for now, the solution is quite fine, according to me. When we turn back for this question to refactor it, we can think about making it leaner.

matrix[i][rowIndex] = ch;
int letterIndex = letterIndex(ch);
if (trieNodeState[i].children[letterIndex] == null) break;
trieNodeStateNext[i] = trieNodeState[i].children[letterIndex];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that trieNodeStateNext doesn't do anything. If I'm not mistaken, we can remove it.

Copy link
Collaborator Author

@altay9 altay9 Jul 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has a function as a kind of "backtracking" to the older "trieNodeState" keeping the older state immutable.
But, we can try removing of course.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see it being inputted into dfs. It makes more sense now, as we are traversing after some prefix already gone through.

TrieNode[] trieNodeStateNext = new TrieNode[trieNodeState.length];
for (String candidate : trieNodeState[rowIndex].list) {

if (isSymmetric(matrix, candidate, rowIndex, trieNodeState, trieNodeStateNext)){
Copy link
Collaborator

@ErdemT09 ErdemT09 Jul 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: isSymmetric() method handles the backtracking part too. As we call the method, it overrides the character matrix with the candidate string. If it's okay, we continue with it. If it's not symmetric, we don't. Either way, it get's overriden in the next function call.

matrix[i][rowIndex] = ch;
int letterIndex = letterIndex(ch);
if (trieNodeState[i].children[letterIndex] == null) break;
trieNodeStateNext[i] = trieNodeState[i].children[letterIndex];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows duplicate usage of words, as the problem allows.

Copy link
Collaborator

@ErdemT09 ErdemT09 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such string algorithms are something that we have not worked on in this repository. This is a good example for further algorithms we might examine such suffix arrays and trees.

@altay9 altay9 merged commit 6465059 into master Jul 18, 2021
@altay9 altay9 deleted the 425._Word_Squares_ branch July 18, 2021 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

425. Word Squares

3 participants