美文网首页C++互联网科技程序员
四种方法求最长回文串

四种方法求最长回文串

作者: 海天一树X | 来源:发表于2018-03-03 19:13 被阅读82次

    所谓回文串,就是正着读和倒着读结果都一样的回文字符串。
    比如:
    a, aba, abccba都是回文串,
    ab, abb, abca都不是回文串。

    一、暴力法

    最容易想到的就是暴力破解,求出每一个子串,之后判断是不是回文,找到最长的那个。

    求每一个子串时间复杂度O(N^2), 判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。

    #include <iostream>
    using namespace std;
    
    string longestPalindrome(string &s)
    {
        int len = s.size();                  //字符串长度
        int maxlen = 1;                      //最长回文字符串长度
        int start = 0;                       //最长回文字符串起始地址
        for(int i = 0; i < len; i++)         //起始地址
        {
            for(int j = i + 1; j < len; j++) //结束地址
            {
                int tmp1 = i, tmp2 = j;
                while(tmp1 < tmp2 && s.at(tmp1) == s.at(tmp2))//判断是不是回文
                {
                    tmp1++;
                    tmp2--;
                }
    
                if(tmp1 >= tmp2 && j - i + 1 > maxlen)
                {
                    maxlen = j - i + 1;
                    start = i;
                }
            }
        }
    
        return s.substr(start, maxlen);
    }
    
    int main()
    {
        string s;
        cout << "Input source string: ";
        cin >> s;
        cout << "The longest palindrome: " << longestPalindrome(s);
        return 0;
    }
    

    运行结果:

    Input source string: abbacdeedc
    The longest palindrome: cdeedc
    

    二、动态规划

    设状态dp[j][i]表示索引j到索引i的子串是否是回文串。则转移方程为:

    1.png

    则dp[j][i]为true时表示索引j到索引i形成的子串为回文子串,且子串起点索引为j,长度为i - j + 1。
    算法时间复杂度为O(N ^ 2)。

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    string longestPalindrome(string s)
    {
        const int n = s.size();
        bool dp[n][n];
        memset(dp, 0, sizeof(dp));
    
        int maxlen = 1;     //保存最长回文子串长度
        int start = 0;      //保存最长回文子串起点
        for(int i = 0; i < n; ++i)
        {
            for(int j = 0; j <= i; ++j)
            {
                if(i - j < 2)
                {
                    dp[j][i] = (s[i] == s[j]);
                }
                else
                {
                    dp[j][i] = (s[i] == s[j] && dp[j + 1][i - 1]);
                }
    
                if(dp[j][i] && maxlen < i - j + 1)
                {
                    maxlen = i - j + 1;
                    start = j;
                }
            }
        }
    
        return s.substr(start, maxlen);
    }
    
    int main()
    {
        string s;
        cout << "Input source string: ";
        cin >> s;
        cout << "The longest palindrome: " << longestPalindrome(s);
        return 0;
    }
    

    三、中心扩展法

    中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
    需要考虑两种情况:
    长度为奇数的回文串,比如a, aba, abcba
    长度为偶数的回文串,比如aa, abba

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    string longestPalindrome(string &s)
    {
        const int len = s.size();
        int maxlen = 1;
        int start = 0;
    
        for(int i = 0; i < len; i++)//求长度为奇数的回文串
        {
            int j = i - 1, k = i + 1;
            while(j >= 0 && k < len && s.at(j) == s.at(k))
            {
                if(k - j + 1 > maxlen)
                {
                    maxlen = k - j + 1;
                    start = j;
                }
    
                j--;
                k++;
            }
        }
    
        for(int i = 0; i < len; i++)//求长度为偶数的回文串
        {
            int j = i, k = i + 1;
            while(j >= 0 && k < len && s.at(j) == s.at(k))
            {
                if(k - j + 1 > maxlen)
                {
                    maxlen = k - j + 1;
                    start = j;
                }
    
                j--;
                k++;
            }
        }
    
        return s.substr(start, maxlen);
    }
    
    
    int main()
    {
        string s;
        cout << "Input source string: ";
        cin >> s;
        cout << "The longest palindrome: " << longestPalindrome(s);
        return 0;
    }
    

    四、Manacher算法

    Manacher算法的时间复杂度为O(N),具体可参考:
    https://www.cnblogs.com/grandyang/p/4475985.html



    更多内容请关注微信公众号


    feicuisenlin_12x12.jpg

    相关文章

      网友评论

        本文标题:四种方法求最长回文串

        本文链接:https://www.haomeiwen.com/subject/eqkxfftx.html