Every day a Leetcode
题目来源:3045. 统计前后缀下标对 II
解法1:字典树
将这个列表哈希化:idx = (s[i] - ‘a’) * 26 + (s[j] - ‘a’)。
枚举 t=words[j],怎么统计有多少个 s=words[i] 是 t 的前缀?
这可以用字典树解决,在遍历 words 的同时,维护每个字符串的出现次数。当我们遍历 t 时,同时遍历字典树上的对应节点,并把 t 插入字典树。
代码:
/*
* @lc app=leetcode.cn id=3045 lang=cpp
*
* [3045] 统计前后缀下标对 II
*/
// @lc code=start
// 字典树
class Solution
{
public:
struct Trie
{
unordered_map<int, Trie *> childs;
int cnt = 0;
};
Trie *trie = new Trie();
void add(const string &s)
{
Trie *cur = trie;
int n = s.size();
for (int i = 0, j = n - 1; i < n; ++i, --j)
{
int idx = (s[i] - 'a') * 26 + (s[j] - 'a');
if (!cur->childs.count(idx))
{
cur->childs[idx] = new Trie();
}
cur = cur->childs[idx];
cur->cnt += 1;
}
}
int query(const string &s)
{
Trie *cur = trie;
int n = s.size();
for (int i = 0, j = n - 1; i < n; ++i, --j)
{
int idx = (s[i] - 'a') * 26 + (s[j] - 'a');
if (!cur->childs.count(idx))
return 0;
cur = cur->childs[idx];
}
return cur->cnt;
}
long long countPrefixSuffixPairs(vector<string> &words)
{
int n = words.size();
long long ans = 0;
for (int i = n - 1; i >= 0; --i)
{
ans += query(words[i]);
add(words[i]);
}
return ans;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(L),其中 L 为所有 words[i] 的长度之和。
空间复杂度:O(L),其中 L 为所有 words[i] 的长度之和。