Three ways to solve the "Longest Palindromic Substring" problem

    namespace v1
    {
        namespace details
        {
            inline bool is_palindromic(int i, int j, std::vector<std::vector<std::pair<int, int>>> & cache)
            {
                std::pair<int, int> deux = cache[i][j];
                return (deux.first == i && deux.second == j);
            }

            inline int get_distance(std::pair<int, int> deux)
            {
                return (deux.second - deux.first + 1);
            }
        }

        std::string get_longest_palindromic_substring(const char * input)
        {
            std::string ret;
            int n = static_cast<int>(input != NULL ? strlen(input) : 0);
            if (n > 1) {
                std::vector<std::vector<std::pair<int, int>>> cache(n, std::vector<std::pair<int, int>>(n));
                for (int i = 0; i < n; ++i) {
                    cache[i][i].first = i;
                    cache[i][i].second = i;
                }
                for (int i = 0, ie = n - 1; i < ie; ++i) {
                    int j = i + 1;
                    cache[i][j] = input[i] == input[j] ? std::make_pair(i, j) : cache[i][i];
                }
                for (int d = 2; d < n; ++d) {
                    for (int i = 0, ie = n - d; i < ie; ++i) {
                        int j = i + d;
                        int ni = i + 1, nj = j - 1;

                        auto c1 = cache[ ni ][ j ];
                        if ( details::get_distance( cache[ i ][ nj ] ) > details::get_distance( cache[ ni ][ j ] ) ) {
                            c1 = cache[ i ][ nj ];
                        }

                        if ( input[ i ] == input[ j ] ) {
                            auto c2 = cache[ ni ][ nj ];
                            if ( details::is_palindromic( ni, nj, cache ) ) {
                                c2 = std::make_pair( i, j );
                            }
                            if ( details::get_distance( c1 ) < details::get_distance( c2 ) ) {
                                c1 = c2;
                            }
                        }

                        cache[i][j] = c1;
                    }
                }
                auto deux = cache[0][n - 1];
                ret.assign(input + deux.first, input + deux.second + 1);
            }
            else if (n == 1) {
                ret.push_back(input[0]);
            }
            return std::move(ret);
        }
    }



    namespace v2
    {
        namespace details
        {
            std::pair<int, int> get_palindromic_substring(int first, int second, const char * input, int n)
            {
                while (first > -1 && second < n && input[first] == input[second]) {
                    --first;
                    ++second;
                }
                return std::make_pair(first + 1, second - 1);
            }

            bool larger(std::pair<int, int> p1, std::pair<int, int> p2)
            {
                int d1 = p1.second - p1.first + 1;
                int d2 = p2.second - p2.first + 1;
                return d1 > d2;
            }
        }

        std::string get_longest_palindromic_substring(const char * input)
        {
            int n = static_cast<int>(input != NULL ? strlen(input) : 0);
            std::string ret;
            if (n > 1) {
                std::pair<int, int> section = { 0, -1 };
                for (int i = 1, ie = n * 2; i < ie; ++i) {
                    int second = i / 2;
                    int first = second - (((i & 1) + 1) & 1);
                    auto result = details::get_palindromic_substring(first, second, input, n);
                    //printf( "%s\n", std::string( input + result.first, input + result.second + 1 ).c_str() );
                    if ( details::larger( result, section ) ) {
                        section = result;
                    }
                }
                ret.assign(input + section.first, input + section.second + 1);
            }
            else if (n == 1) {
                ret.push_back(input[0]);
            }
            return std::move(ret);
        }
    }



    namespace v3
    {
        namespace details
        {
            std::vector<char> pre_process(const char * input)
            {
                assert(input != NULL && input[0] != 0);
                size_t n = strlen(input);
                std::vector<char> ret;
                ret.reserve((n + 1) * 2);
                for (; *input != 0; ++input) {
                    ret.push_back( '\0' );
                    ret.push_back( input[ 0 ] );
                }
                ret.push_back( '\0' );
                return std::move( ret );
            }
        }

        std::string get_longest_palindromic_substring(const char * input)
        {
            int n = static_cast<int>(input != NULL ? strlen(input) : 0);
            std::string ret;
            if (n > 1) {
                std::vector<char> data(details::pre_process(input));
                n = static_cast<int>(data.size());
                std::vector<int> cache(n, 0);
                int center = 0, right = 0, i, l;
                for (i = 1, --n; i < n; ++i) {
                    int mi = center * 2 - i;
                    cache[i] = i < right ? std::min(right - i, cache[mi]) : 0;

                    l = cache[i];
                    int il = i - cache[i] - 1, ir = i + cache[i] + 1;
                    while (il > -1 && ir < n && data[il] == data[ir]) {
                        --il;
                        ++ir;
                        ++l;
                    }
                    cache[i] = l;
                    --ir;
                    if ( ir > right ) {
                        right = ir;
                        center = i;
                    }
                }

                l = 0;
                for (i = 0; i < n; ++i) {
                    if (cache[i] > l) {
                        l = cache[i];
                        center = i;
                    }
                }
                i = center / 2;
                l /= 2;
                ret.assign(input + i - l, input + i + l + (center & 1));
            }
            else if (n == 1) {
                ret.push_back(input[0]);
            }
            return std::move(ret);
        }
    } 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值