最长回文子串的寻找C++实现附代码

最长回文子串的寻找C++实现附代码

思路一

依次穷举所有子串。

比如对于字符串 abcdefg

依次穷举

第一趟
a  ab  abc  abcd  abcde  abcdef  abcdefd
第二趟
b  bc  bcd  bcde  bcdef  bcdefg
依此类推

判断一个字符串是否为回文:

int main() {
     int flag = 1;
     string s = "a";//测试字符串
     if (s.length() == 0) {
          printf("字符串为空");
          return -1;
     }
     for (int m = 0; m < s.length()/2; m++) {
          if (s[m] != s[s.length() - m - 1])
               flag = 0;
     }
     if (flag == 1)
          printf("yes");
     else
          printf("no");
     return 0;
}

寻找最长回文子串完整代码如下

其实有些遍历可以提前终止。只要[length-1]或者[length-2]与当前遍历的字符所连成的字符串是回文串便可以直接返回了,因为它一定是最长的。但是由于这个方法中的串是从头向尾延伸的,所以差别不大。如果串从两端向中心延伸,可以节省一些时间。

#include 
#include 
using namespace std;
class Solution {
public:
     string longestPalindrome(string s) {
          int leng = s.length();
          int flag = 1;
          string res;//存储每次检查的子串
          string res1 = "";
          res1 = res1 + s[0];//存储最终结果
          for (int i = 0; i < leng; i++) {
               for (int j = i; j < leng; j++) {
                    flag = 1;
                    res = s.substr(i, (j - i + 1));//提取子串
                    for (int m = 0; m < res.length() / 2; m++) {
                         if (res[m] != res[res.length() - m - 1])
                              flag = 0;
                    }//判断是否回文
                    if (flag == 1) {
                         if ((res.length()) > res1.length()) {
                              res1 = res;
                         }
                    }
               }
          }
          return res1;

     }
};

int main() {
     string s = "ac";//测试字符串
     string res;
     Solution cl;
     res=cl.longestPalindrome(s);
     cout << res << endl;
     return 0;
}

这个方法效率贼低。提交的时候超时了。时间复杂度达到了O(n^3)

(要上课了,等会下课再搞,我先溜了)

来了来了

思路2(胡思乱想的垃圾,跳过即可)

串从两端向中间延伸。

其实这个思路是我最先想出来的,但是实现的时候没有成功,现在上完了课,来看一下是不是行得通。

先来分析一波。

首先思考回文子串的特征。两个及以上长度的回文子串有一个共同的特征:首尾字符必定是相同的。我们以此为出发点,思考以下的步骤。

从头扫描字符串进行回文子串的判断,在这个过程中不断更新回文子串,直至得出最优解。具体操作如下:

对于字符串asgafa

首先扫描字符a,记录此时的扫描下表,为0,然后,从尾部开始寻找a,当找到a的时候,记下此时的位置,对于此字符串,得出此时位置为下标5,对0-5子串进行回文子串检测,如果是回文子串,则直接返回即可。如果不是,继续从后向前寻找a,直至收尾相碰。这样的话,也是三层for循环,差别不大,实际上还是遍历。如果想要提高效率,需要寻找更好的检测条件,减除那些不必要的遍历,此方法在停止遍历的条件有点混乱,仅能去除很少的一部分特殊字符串的不必要遍历,我试一试吧,看能不能AC。

之后,如果没有得到回文子串,直接返回首字符即可,即把长度为1的回文子串进行单独处理,上述过程寻找的是长度大于等于2的回文子串。

代码如下

#include 
#include 
using namespace std;
class Solution {
public:
     string longestPalindrome(string s) {
          int len = s.length();
          string temps;
          string res;
          int suc = 1;
          int flag;
          for(int i=0;i<len-1;i++){//头部走到[len-2]就可以停下了
               for (int j = len - 1; j > i; j--) {
                    flag = 1;
                    if (s[i] == s[j]) {
                         temps = s.substr(i, j - i + 1);
                         for (int m = 0; m < temps.length() / 2; m++) {
                              if (temps[m] != temps[temps.length() - m - 1])
                                   flag = 0;
                         }
                         if (flag == 0)
                              continue;//继续向前寻找
                         else {
                              if ((j == (len - 1) || j == (len - 2))&&suc<(j-i+1)) {//找到
                                   return temps;
                              }
                              else {
                                   if (suc < (j - i + 1)) {
                                        res = temps;
                                        suc = j - i + 1;
                                   }
                              }
                         }
                    }
               }
          }
          if (suc == 1) {
               res = res + s[0];
          }
          return res;
     }
};

int main() {
     string s = "p";//测试字符串
     string res;
     Solution cl;
     res = cl.longestPalindrome(s);
     cout << res << endl;
     return 0;
}

比思路1快了一些。但还是超出了时间限制。这个方法仅仅对一些特殊的字符串速度快,行不通。

菜狗只好去看题解了。

题解有几种方法,包括但不限于中心扩散法、动态规划方法、Manacher算法。以下分别进行分析。

(得,一下午加一晚上就弄一道题,我可真棒)

题解链接:
https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/

动态规划代码:

class Solution {
public:
     string longestPalindrome(string s) {
          int len = s.length();
          int head = 0;
          int suc = 1;
          int len2;
          vector<vector<int>> table(len, vector<int>(len));
          for (int i = 0; i < len - 1; i++) {
               table[i][i] = 1;
          }
          for (int j = 0; j < len; j++) {
               for (int i = 0; i < j; i++) {
                    if ((j - i) == 1) {
                         if (s[i] == s[j]) {
                              table[i][j] = 1;
                         }
                         else
                              table[i][j] = 0;
                    }
                    else {
                         table[i][j] = (!(s[i] ^ s[j])) && (table[i + 1][j - 1]);
                    }
                    if (table[i][j] == 1) {
                         len2 = j - i + 1;
                         if (suc < len2) {
                              suc = len2;
                              head = i;
                         }
                    }
               }
          }
          return s.substr(head, suc);
     }
};

你可能感兴趣的:(数据结构与算法/刷题笔记,算法导论,c++)