嘗試着理解了一下Trie樹,原理解釋見:https://discuss.leetcode.com/topic/39585/o-n-k-2-java-solution-with-trie-structure-n-total-number-of-words-k-average-length-of-each-word
我把代碼改成了C++,使用了shared_ptr,做了簡單的註釋,已經AC
class TrieNode {
public:
vector<shared_ptr<TrieNode>> next;
int index=-1;//截止到當前節點爲止是否構成words中的一個字符串,並記錄字符串的索引位置
vector<int> list;//截止到當前節點爲止形成了一個字符串A(可能是words中的元素,也可能不是),list裏保存words中所有含有字符串A的元素的位置
TrieNode() { next.resize(26); }
};
class Solution {
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
vector<vector<int>> res;
shared_ptr<TrieNode> root(new TrieNode());
for (int i = 0; i < words.size(); i++)
addWord(root, words[i], i);
for (int i = 0; i < words.size(); i++)
search(words, i, root, res);
return res;
}
void addWord(shared_ptr<TrieNode> root, string& word, int index) {
for (int i = word.size() - 1; i >= 0; i--) {
int j = word[i] - 'a';
if (root->next[j] == NULL)
root->next[j] = make_shared<TrieNode>();
if (isPalindrome(word, 0, i))
root->list.push_back(index);
root = root->next[j];
}
root->list.push_back(index);
root->index = index;
}
void search(vector<string>& words, int i, shared_ptr<TrieNode> root, vector<vector<int>>& res) {
for (int j = 0; j < words[i].length(); j++) {
//下面的這個if用來處理“ac”,“cabb”這類情況,這裏就體現出TrieNode類的設計的tricky之處了
if (root->index >= 0 && root->index != i && isPalindrome(words[i], j, words[i].length() - 1)) {
res.push_back(vector<int>{i, root->index});
}
root = root->next[words[i][j] - 'a'];
if (root == NULL) return;
}
//下面這個循環用來處理“aaa”,“aaa”這類情況
for (int j : root->list) {
if (i == j) continue;
res.push_back(vector<int>{i, j});
}
}
bool isPalindrome(string& word, int i, int j) {
while (i < j) {
if (word[i++] != word[j--]) return false;
}
return true;
}
};