Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1813. Sentence Similarity III - Leetcode Solution

Problem Description

The Sentence Similarity III problem asks you to determine whether two sentences, represented as strings sentence1 and sentence2, are similar under a specific definition.

Two sentences are considered similar if it is possible to insert an arbitrary (possibly empty) sequence of words into one of them (at any position, including the start or end) so that the two sentences become exactly equal.

Key constraints:

  • Sentences consist of words separated by a single space.
  • Words are non-empty and contain only lowercase letters.
  • You can insert words anywhere (start, middle, or end), but you cannot remove or replace words.
  • Each word can only be used as itself; no reordering or substitution is allowed.
Goal:
Return True if the two sentences are similar according to the rule above, and False otherwise.

Thought Process

At first glance, the problem seems to ask if we can make two sentences equal by inserting words anywhere. But a closer look reveals:

  • If one sentence is a sublist of the other (possibly after inserting words at the beginning or end), they are similar.
  • The only way to transform one into the other is by adding words, not deleting or reordering.
  • So, the core idea is: does one sentence appear as a prefix and/or suffix of the other?

A brute-force approach would be to try all possible insertions, but that's computationally infeasible. Instead, we can look for the longest matching prefix and suffix between the two sentences.

If, after removing the common prefix and suffix, the remaining words (if any) in the shorter sentence can be "inserted" into the longer one, then the sentences are similar.

Solution Approach

We'll solve the problem efficiently by following these steps:

  1. Split both sentences into lists of words.
  2. Identify the shorter and longer sentence. This simplifies logic, as we can always try to "insert" words into the longer one.
  3. Find the longest matching prefix (starting from the first word) between the two lists.
  4. Find the longest matching suffix (starting from the last word) between the two lists, making sure not to overlap with the prefix.
  5. Check if all words of the shorter sentence are covered by the prefix and suffix matches. If so, the sentences are similar.

Why this works:
  • Any unmatched words in the longer sentence can be "explained" by insertions.
  • As long as the shorter sentence's words appear in order as a prefix and/or suffix, we can always insert extra words into the longer sentence to match.

Implementation tips:
  • Use two pointers to scan for prefix and suffix matches.
  • Be careful with edge cases: empty sentences, full matches, or no matches.

Example Walkthrough

Example:
sentence1 = "my name is alice"
sentence2 = "my alice"

Step-by-step:

  1. Split into words:
    words1 = ["my", "name", "is", "alice"]
    words2 = ["my", "alice"]
  2. Identify shorter sentence: words2 (length 2)
  3. Check prefix: "my" matches "my" (index 0)
  4. Check suffix: "alice" matches "alice" (last index)
  5. Prefix + suffix covers all of words2 (2 words total)
  6. So, sentence1 can become sentence2 by inserting "name is" in the middle.
Result: The sentences are similar, so we return True.

Counter-example:
sentence1 = "hello world"
sentence2 = "world hello"
No prefix or suffix matches, so they are not similar.

Time and Space Complexity

Brute-force approach:

  • Would involve generating all possible insertions, which is exponential in the number of words. Not practical.
Optimized approach (prefix/suffix matching):
  • Splitting sentences: O(N + M), where N and M are the number of words in each sentence.
  • Prefix and suffix matching: O(min(N, M)) for each.
  • Overall Time Complexity: O(N + M)
  • Space Complexity: O(N + M) for storing split word lists.

This is efficient and suitable for even long sentences.

Code Implementation

class Solution:
    def areSentencesSimilar(self, sentence1: str, sentence2: str) -> bool:
        words1 = sentence1.split()
        words2 = sentence2.split()
        
        # Always let words1 be the longer one
        if len(words1) < len(words2):
            words1, words2 = words2, words1
        
        n, m = len(words1), len(words2)
        # Check prefix
        i = 0
        while i < m and words1[i] == words2[i]:
            i += 1
        # Check suffix
        j = 0
        while j < m - i and words1[n - 1 - j] == words2[m - 1 - j]:
            j += 1
        return i + j == m
      
class Solution {
public:
    bool areSentencesSimilar(string sentence1, string sentence2) {
        vector<string> words1 = split(sentence1);
        vector<string> words2 = split(sentence2);
        if (words1.size() < words2.size()) swap(words1, words2);
        int n = words1.size(), m = words2.size();
        int i = 0;
        while (i < m && words1[i] == words2[i]) ++i;
        int j = 0;
        while (j < m - i && words1[n - 1 - j] == words2[m - 1 - j]) ++j;
        return i + j == m;
    }
private:
    vector<string> split(const string& s) {
        vector<string> res;
        istringstream iss(s);
        string word;
        while (iss >> word) res.push_back(word);
        return res;
    }
};
      
class Solution {
    public boolean areSentencesSimilar(String sentence1, String sentence2) {
        String[] words1 = sentence1.split(" ");
        String[] words2 = sentence2.split(" ");
        if (words1.length < words2.length) {
            String[] temp = words1; words1 = words2; words2 = temp;
        }
        int n = words1.length, m = words2.length;
        int i = 0;
        while (i < m && words1[i].equals(words2[i])) i++;
        int j = 0;
        while (j < m - i && words1[n - 1 - j].equals(words2[m - 1 - j])) j++;
        return i + j == m;
    }
}
      
var areSentencesSimilar = function(sentence1, sentence2) {
    let words1 = sentence1.split(' ');
    let words2 = sentence2.split(' ');
    if (words1.length < words2.length) {
        [words1, words2] = [words2, words1];
    }
    let n = words1.length, m = words2.length;
    let i = 0;
    while (i < m && words1[i] === words2[i]) i++;
    let j = 0;
    while (j < m - i && words1[n - 1 - j] === words2[m - 1 - j]) j++;
    return i + j === m;
};
      

Summary

The Sentence Similarity III problem boils down to checking if the shorter sentence appears as a prefix and/or suffix of the longer one, in order. By using two pointers to scan for matching words at the start and end, we can efficiently determine similarity in linear time. This approach avoids brute-force insertions, leverages the constraints, and provides a clean, elegant solution.