• LeetCode "Palindrome Pairs"


    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

  • 相关阅读:
    字符串删减
    iOS-AFNetworking与ASIHTTPRequest的区别
    iOS-清理缓存
    iOS-addSubView时给UIView添加效果
    iOS-明杰解决字段冲突,及数组映射
    iOS-开发将文本复制到剪切板
    iOS-加载html字符串
    iOS-UILabel加线
    iOS-获取webView的高度
    iOS-plist文件的写读
  • 原文地址:https://www.cnblogs.com/tonix/p/5261941.html
Copyright © 2020-2023  润新知