Leetcode 336. Palindrome Pairs 給出一種遍歷字串迴文子串中心的方法
阿新 • • 發佈:2018-11-11
題意
- 給你n個不同的字串,讓你找出所有的字串對(i, j),使得s(i) + s(j)是迴文串且i不等於j
思路
- 這題沒有給資料範圍,所以你其實不知道應該給什麼複雜度的演算法,我看了眼Discussion,先確定了下需要的複雜度
- 複雜度是O(n * k ^ 2),其中k是字串的平均長度
- 演算法思路並不複雜,考慮第i個字串,如果s = s(i) + s(j)是答案之一,且i是較長的字串,那麼s的迴文中心一定出現在 s(i)中,所以我們只要遍歷s(i)可能的迴文中心t即可,不失一般性,我們假設len(s(i, 1…t)) > len(s(i, t…l)),其中l = len(s(i)),此時需要在s(i)右側拼接字串,且需要拼接的字串已經確定了,我們可以通過hash map快速找到對應字串的id
- 需要注意的是如果兩個拼接的字串長度一樣,則可能重複新增到ans list裡,這裡我採用的方法是如果發現拼接的字串長度相等,則只有j > i時我才把該結果加入list中
- 最後就是如何比較容易的實現遍歷字串迴文子串中心的方法,我設計了一種還可以的策略,這裡記錄一下~
遍歷字串迴文子串中心的方法
不難發現,對於一個長度為n的字串,可能的迴文子串中心有2n + 1個
- 間隔插入特殊字元:
- 如:aba =》 #a#b#a#
- 這種方法一般用在曼徹斯特演算法中
- 直接遍歷:
for (int
- 間隔插入特殊字元:
實現
class Solution {
public:
vector<vector<int> > res;
unordered_map<string, int> mapp;
int n;
inline vector<int> get_pair(int x, int y){
vector <int> res;
res.push_back(x);
res.push_back(y);
return res;
}
void go(string& s, int idx, bool flag){
int len = s.length();
for (int m = len; m <= 2 * len; m++){
int ls = m / 2 - 1;
int rs = m / 2 + (m & 1);
int r = rs, l = ls;
for (;r < m; r++, l--){
if (s[l] != s[r]){
break;
}
}
if (r < len){
continue;
}
string tmp = "";
for (; l >= 0; l--){
tmp += s[l];
}
if (flag){
auto it = mapp.find(tmp);
if (it != mapp.end() && it->second != idx){
if (m < 2 * len || idx < it->second){
res.push_back(get_pair(idx, it->second));
}
}
}
else{
reverse(tmp.begin(), tmp.end());
auto it = mapp.find(tmp);
if (it != mapp.end() && it->second != idx){
if (m < 2 * len || idx < it->second){
res.push_back(get_pair(it->second, idx));
}
}
}
}
}
vector<vector<int>> palindromePairs(vector<string>& words) {
n = words.size();
for (int i=0;i<n;i++){
mapp[words[i]] = i;
}
for (int i=0;i<n;i++){
string s = words[i];
go(s, i, true);
reverse(s.begin(), s.end());
go(s, i, false);
}
return res;
}
};