暴力法需要O(n^2*L),即遍历所有单词的两两前后组合,每个合并的单词再判断是否为回文串。
优化方法是,对于每一个单词word1,能够与之相加得到回文串的单词word2必定满足:
word1 + word2 = palindrome
相同长度的:prefix(word1) = reverse(word2)
因此可预处理用hashmap存下所有单词的reverse
然后枚举每个单词的前缀,即将word拆分成left和right两部分,left部分去匹配map中是否有相对应相等的word,right部分判断是否是回文串
需要注意处理的是""的情况,""加任何回文串都是回文串,加在前面和后面算两个答案
class Solution {
public:
bool is(string s) {
int i = 0, j = s.length() - 1;
while (i < j) {
if (s[i++] != s[j--]) return false;
}
return true;
}
vector<vector<int>> palindromePairs(vector<string>& words) {
int n = words.size();
vector<vector<int>> ans;
unordered_map<string, int> mp;
for (int i = 0; i < n; i++) {
string word = words[i];
reverse(word.begin(), word.end());
mp[word] = i;
}
// corner case
if (mp.find("") != mp.end()) {
for (int i = 0; i < n; i++) {
string word = words[i];
if (word != "" && is(word)) {
ans.push_back({mp[""], i});
}
}
}
for (int i = 0; i < n; i++) {
string word = words[i];
for (int j = 0; j < word.length(); j++) {
string left = word.substr(0, j);
string right = word.substr(j, word.length() - j);
if (mp.find(left) != mp.end() && mp[left] != i && is(right)) {
ans.push_back({i, mp[left]}); // left = "", then ans add {i, ""}
}
if (mp.find(right) != mp.end() && mp[right] != i && is(left)) {
ans.push_back({mp[right], i}); // right never equals to "", so add corner cases before
}
}
}
return ans;
}
};