1. 程式人生 > >Leetcode 336. Palindrome Pairs 給出一種遍歷字串迴文子串中心的方法

Leetcode 336. Palindrome Pairs 給出一種遍歷字串迴文子串中心的方法

題意

  • 給你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個

    1. 間隔插入特殊字元:
      • 如:aba =》 #a#b#a#
      • 這種方法一般用在曼徹斯特演算法中
    2. 直接遍歷:
      for (int
      m = 0; m <= 2 * len; m++){ int l_start = m / 2 - 1; int r_start = m/2 + (m & 1); //do }

實現

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; } };