leetcode - 3045 / 3042. Count Prefix and Suffix Pairs II

Description

You are given a 0-indexed string array words.

Let’s define a boolean function isPrefixAndSuffix that takes two strings, str1 and str2:

isPrefixAndSuffix(str1, str2) returns true if str1 is both a prefix and a suffix of str2, and false otherwise.
For example, isPrefixAndSuffix(“aba”, “ababa”) is true because “aba” is a prefix of “ababa” and also a suffix, but isPrefixAndSuffix(“abc”, “abcd”) is false.

Return an integer denoting the number of index pairs (i, j) such that i < j, and isPrefixAndSuffix(words[i], words[j]) is true.

Example 1:

Input: words = ["a","aba","ababa","aa"]
Output: 4
Explanation: In this example, the counted index pairs are:
i = 0 and j = 1 because isPrefixAndSuffix("a", "aba") is true.
i = 0 and j = 2 because isPrefixAndSuffix("a", "ababa") is true.
i = 0 and j = 3 because isPrefixAndSuffix("a", "aa") is true.
i = 1 and j = 2 because isPrefixAndSuffix("aba", "ababa") is true.
Therefore, the answer is 4.

Example 2:

Input: words = ["pa","papa","ma","mama"]
Output: 2
Explanation: In this example, the counted index pairs are:
i = 0 and j = 1 because isPrefixAndSuffix("pa", "papa") is true.
i = 2 and j = 3 because isPrefixAndSuffix("ma", "mama") is true.
Therefore, the answer is 2.  

Example 3:

Input: words = ["abab","ab"]
Output: 0
Explanation: In this example, the only valid index pair is i = 0 and j = 1, and isPrefixAndSuffix("abab", "ab") is false.
Therefore, the answer is 0.

Constraints:

1 <= words.length <= 10^5
1 <= words[i].length <= 10^5
words[i] consists only of lowercase English letters.
The sum of the lengths of all words[i] does not exceed 5 * 10^5.

Solution

3042 is just an easier version with looser constrains. For this problem I do with trie tree.

My thoughts:
Use a trie tree to store all the words, and then search and add the is_end to the final result => according to the description, i has to be: i < j, and suffix is not just the reversed prefix
=> build a prefix trie tree and a suffix prefix tree => what if a word is a prefix of word a and a suffix of word b?
=> instead of using boolean is_end, use a set to store the word => what if a word is a prefix of 2 same words? like [a, aa, aa]?
=> instead of using a set, use a hash map => memory limit error
=> pass a word_mapping to the object, store the index of the word instead of the word => TLE

Code

class TrieNode:
    def __init__(self) -> None:
        self.child = {}
        self.is_end = {}

class TrieTree:
    def __init__(self, word_mapping: dict, is_reversed=False) -> None:
        self.root = TrieNode()
        self.is_reversed = is_reversed
        self.word_mapping = word_mapping
    
    def insert(self, word: str) -> None:
        node = self.root
        for each_char in word:
            if each_char not in node.child:
                node.child[each_char] = TrieNode()
            node = node.child[each_char]
            word_key = self.word_mapping[word if not self.is_reversed else word[::-1]]
            node.is_end[word_key] = node.is_end.get(word_key, 0) + 1
    
    def search(self, word: str) -> dict:
        node = self.root
        for each_char in word:
            if each_char not in node.child:
                return {}
            node = node.child[each_char]
        return node.is_end

class Solution:
    def countPrefixSuffixPairs(self, words: List[str]) -> int:
        word_mapping = {words[i]: i for i in range(len(words))}
        prefix_tree = TrieTree(word_mapping)
        suffix_tree = TrieTree(word_mapping, is_reversed=True)
        res = 0
        for each_word in words[::-1]:
            common_keys = prefix_tree.search(each_word).keys() & suffix_tree.search(each_word[::-1]).keys()
            for each_key in common_keys:
                res += min(prefix_tree.search(each_word)[each_key], suffix_tree.search(each_word[::-1])[each_key])
            prefix_tree.insert(each_word)
            suffix_tree.insert(each_word[::-1])
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值