Problem Statement
Brute Force [Accepted]
class Solution:
def countPrefixSuffixPairs(self, words: List[str]) -> int:
N = len(words)
res = 0
def isPrefixAndSuffix(w1, w2):
if len(w1) > len(w2):
return 0
i, j = 0, 0
n = len(w1)
for i in range(n):
if w1[i] != w2[j]:
return 0
j += 1
i, j = n - 1, len(w2) - 1
for i in range(n - 1, -1, -1):
if w1[i] != w2[j]:
return 0
j -= 1
return 1
for i in range(N):
for j in range(i + 1, N):
res += isPrefixAndSuffix(words[i], words[j])
return res
Editorial
Approach 1: Brute Force
class Solution:
def countPrefixSuffixPairs(self, words: List[str]) -> int:
n = len(words)
count = 0
# Step 1: Iterate through each pair of words
for i in range(n):
for j in range(i + 1, n):
str1 = words[i]
str2 = words[j]
# Step 2: Skip if the first string is larger than the second
if len(str1) > len(str2):
continue
# Step 3: Check if str1 is both the prefix and suffix of str2
if str2.startswith(str1) and str2.endswith(str1):
count += 1
# Step 4: Return the total count of prefix-suffix pairs
return count
- time: O(n^2 * m)
- space: O(1)
Approach 2: Dual Trie
class Node:
def __init__(self):
self.links = [None] * 26
# Check if the character is present in the current node
def _contains(self, c: str) -> bool:
return self.links[ord(c) - ord("a")] is not None
# Insert a new node for the character
def _put(self, c: str, node: "Node") -> None:
self.links[ord(c) - ord("a")] = node
# Get the next node for the character
def _next(self, c: str) -> "Node":
return self.links[ord(c) - ord("a")]
class Trie:
def __init__(self):
self.root = Node()
# Insert a word into the Trie
def insert(self, word: str) -> None:
node = self.root
for c in word:
if not node._contains(c):
node._put(c, Node())
node = node._next(c)
# Check if the Trie contains a given prefix
def starts_with(self, prefix: str) -> bool:
node = self.root
for c in prefix:
if not node._contains(c):
return False
node = node._next(c)
return True
class Solution:
def countPrefixSuffixPairs(self, words: List[str]) -> int:
n = len(words)
count = 0
# Step 1: Iterate over each word
for i in range(n):
prefix_trie = Trie()
suffix_trie = Trie()
# Step 2: Insert the current word into the prefix Trie
prefix_trie.insert(words[i])
# Step 3: Reverse the word and insert it into the suffix Trie
rev_word = words[i][::-1]
suffix_trie.insert(rev_word)
# Step 4: Iterate over all previous words
for j in range(i):
# Step 5: Skip words[j] if it is longer than words[i]
if len(words[j]) > len(words[i]):
continue
# Step 6: Extract the prefix and reversed prefix of words[j]
prefix_word = words[j]
rev_prefix_word = prefix_word[::-1]
# Step 7: Check if words[j] is both a prefix and suffix of words[i]
if prefix_trie.starts_with(
prefix_word
) and suffix_trie.starts_with(rev_prefix_word):
count += 1
# Step 8: Return the total count of valid pairs
return count
- time: O(n^2 * m)
- space: O(n*m)