您的位置:首页 > 大数据 > 人工智能

LeetCode "Palindrome Pairs"

2016-03-10 14:57 567 查看
My first reaction was to use Manacher - which is O(n*k*k) - n is the no. of words, and k is the average length of words.

Code of Manacher based solution is kinda long:

class Solution {
vector<vector<int>> ret;

//    To find lenghth of the leading Palin only
vector<string> manacher(const string &s)
{
size_t slen = s.length();
if (slen < 2) return { s };

//    inserting tokens to original string
string ns = "#";
for (auto c : s)
{
ns += c;
ns += "#";
}

//
size_t len = ns.length();
vector<size_t> rec(len, 0);

int maxi = 1, maxr = 0; vector<int> rs_leading;
int ci = 1, r = 0;
for (size_t i = 1; i < len; i++)
{
int myr = 0;        //    brand new index
if (i <= (ci + r))    //    can be reused due to symmetry
{
myr = std::min(rec[2 * ci - i], (ci + r) - i);
}
//    expand to new inx towards end of string
bool bMis = false;
int max_ex = std::min(len - 1 - i, i);
while (myr < max_ex)
{
myr++;
if (ns[i + myr] != ns[i - myr])
{
bMis = true;
break;
}
}
if (bMis) myr--;

//    book-keeping
rec[i] = myr;
if ((i + myr) > (maxi + maxr))
ci = i, r = myr;

if (myr > maxr)    //     record max
{
maxi = i, maxr = myr;
if (i == myr)
{
rs_leading.push_back(maxr);
}
}
}

//    Retrieve the Palin
vector<string> ret;
for (auto l : rs_leading)
{
string raw = ns.substr(0, l * 2 + 1);
string tmp;
for (auto c : raw)
{
if (c != '#') tmp += c;
}
ret.push_back(tmp);
}
return ret;
}

void handleLeadingPalin(string w, int inxw, unordered_map<string, int> &dict, bool bReversed)
{
vector<string> hPalins = manacher(w);
for (auto hPalin : hPalins)
{
int plen = hPalin.size();
if (plen)
{
string tgt = w.substr(plen);
if (!bReversed)
reverse(tgt.begin(), tgt.end());

if (dict.find(tgt) != dict.end())
{
int inxt = dict[tgt];
if (inxw != inxt)
{
if (!bReversed)
ret.push_back({ inxt, inxw });
else
ret.push_back({ inxw, inxt});
}
}
}
}
}
public:
vector<vector<int>> palindromePairs(vector<string>& words) {

//    Fill out String <-> Index dictionary
unordered_map<string, int> dict;
for (int i = 0; i < words.size(); i ++)
dict[words[i]] = i;

//    Go
for (auto &k : dict)
{
int inx = k.second;

// case 1: reverse the whole string
string tgt1 = k.first;

reverse(tgt1.begin(), tgt1.end());
if (dict.find(tgt1) != dict.end())
{
int inx1 = dict[tgt1];
if (inx1 != inx)
ret.push_back({inx, inx1});
}

// case 2a: leading manacher of key
handleLeadingPalin(k.first, inx, dict, false);

// case 2b: leading manacher of reverse(key)
string tmp = k.first;
reverse(tmp.begin(), tmp.end());
handleLeadingPalin(tmp, inx, dict, true);
}

return ret;
}
};


And please check this concise Python solution - so neat!

https://leetcode.com/discuss/91284/python-solution
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: