zoukankan      html  css  js  c++  java
  • 最长回文字符串

    题目描述:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

    示例 1:

    输入: "babad"
    输出: "bab"
    注意: "aba" 也是一个有效答案。
    

    示例 2:

    输入: "cbbd"
    输出: "bb"

    解析:最长回文字符串就是正过来和反过来一样的字符串,比如上海自来水来自海上,小明到操场操到天明。。

    方法一:从最暴力的方法入手,直接遍历所有的子字符串

     1 class Solution {
     2 public:
     3     string longestPalindrome(string s) {
     4         //暴力解法
     5         int length = s.length();
     6         int max = 0;
     7         string res = "";
     8         for(int i = 0; i < length; i++){
     9             for(int j = i + 1; j <= length; j++){
    10                 string tmp = string(s, i, j - i);
    11                 //cout << tmp << endl;
    12                 if(isPalindrome(tmp) && tmp.length() > max){
    13                     //cout << tmp << endl;
    14                     max = tmp.length();
    15                     res = tmp;
    16                 }
    17             }
    18         }
    19         return res;
    20         
    21     }
    22 
    23     bool isPalindrome(string s){
    24         for(int i = 0; i < s.length() / 2; i++){
    25             if(s[i] != s[s.length() - i - 1]){
    26                 return false;
    27             }
    28         }
    29         return true;
    30     }
    31 };

    分析:遍历子字符串需要n(n - 1)/2,复杂度为O(n^2),每次判断是否为回文字符串的复杂度为O(n),所以,此算法复杂度为O(n^3);

    方法二:通过字符串翻转,然后找到最长公共字串,再判断是否是回文字串

     1 class Solution {
     2 public:
     3     string longestPalindrome(string s) {
     4         string s_resvere = s;
     5         reverse(s_resvere.begin(), s_resvere.end());  // 翻转字符串
     6         return findlongestSubStr(s, s_resvere, s.length());
     7     }
     8 
     9     string findlongestSubStr(string s1, string s2, int length){
    10         bool check = 0;
    11         string res;
    12         for(int step = length; step > 0; step--){
    13             for(int i = 0; i + step - 1 < length; i++){
    14                 string tmp = string(s1, i, step);  //定义一个临时变量,从i下标开始,往后加step个字符串
    15                 if(s2.find(tmp) != -1){
    16                     string rtmp = tmp;
    17                     reverse(rtmp.begin(), rtmp.end());
    18                     if(rtmp == tmp){
    19                         res = tmp;
    20                         check = 1;
    21                         break;
    22                     }
    23                 }
    24             }
    25             if(check) break;
    26         }
    27         return res;
    28     }
    29 };

    分析:此算法的时间复杂度仍然为o(n^3);

     方法三:动态规划,通过动态规划存放之前比较的结果,从而将时间复杂度缩减至O(n^2)

     1 class Solution {
     2 public:
     3     string longestPalindrome(string s) {
     4         int length = s.length();
     5         if(length <= 1) return s;
     6         int max = 1;  //代表最大回文串长度
     7         int start = 0; //代表回文串的起始下标
     8         int dp[1000][1000] = {0}; // 定义一个二维数组,初始化为0,dp[i][j]=1代表从 从i 到 j闭区间内为回文串
     9         for(int i = 0; i < length; i++){   // 进行初始化,如果为dp[i][i]一定为回文串,置为1,同样,两个连续的相同的字符也能组成一个回文串
    10             dp[i][i] = 1;
    11             if(i < length - 1 && s[i] == s[i + 1]) {
    12                 start = i;
    13                 max = 2;
    14                 dp[i][i + 1] = 1;
    15             }
    16         }
    17         for(int size = 3; size <= length; size++){ //之前从2 判断过了, 所以从3开始进行判断
    18             int right;
    19             for(int left = 0; left + size - 1< length; left++){
    20                 right = left + size - 1;
    21                 if(s[left] == s[right] && dp[left + 1][right - 1] == 1){ // 如果左边等于右边,而且中间还是回文串,那么这个[left,right]一定是回文串
    22                     dp[left][right] = 1;
    23                     max = size;
    24                     start = left;
    25                 }
    26             }
    27         }
    28         return s.substr(start, max);
    29     }
    30 };

     方法四:中心扩展算法,通过中心扩展,减少相应的迭代步骤,降低时间复杂度。具体实现:一个回文串的中心可能是一个字符,也可能是两个字符,如果以一个字符为中心,有n个中心,以两个字符为中心,就有n-1个中心,所以一共有2n-1个中心;

     1 class Solution {
     2 public:  
     3     string longestPalindrome(string s) {
     4         int length = s.length();
     5         if(length <= 1) return s;
     6         int max_res = 1;
     7         int start = 0;
     8         for(int i = 0; i < length; i++){
     9             int max1 = maxLength(s, i, i);
    10             int max2 = maxLength(s, i, i + 1);
    11             if(max_res < max(max1, max2)){
    12                 max_res = max(max1, max2);
    13                 start = i - (max_res - 1) / 2;
    14                 //cout << "max = "<< max_res << " " <<" start = " << start << " i = " << i <<endl;
    15             }
    16         }
    17         return s.substr(start, max_res);
    18     }
    19 
    20 private:
    21     int maxLength(string s, int left, int right){  
    22         while(left >= 0 && right < s.length() && s[left] == s[right]) {
    23             left--;
    24             right++;
    25         }
    26         return right - left - 1;
    27     }
    28 };
    
    
  • 相关阅读:
    [算法]全排列类问题
    windows下python安装Numpy和Scipy模块
    EMC校招笔试题目
    word2012写论文之参考文献和图片
    我的MBTI性格测试
    单例模式三境界
    css3滤镜Filter使用
    利用nginx 虚拟主机、请求转发实现不同端口web访问
    使用gitbook 发布一个教程文档网站
    linux 下CentOS 下 npm命令安装gitbook失败的问题
  • 原文地址:https://www.cnblogs.com/zz1314/p/12901450.html
Copyright © 2011-2022 走看看