zoukankan      html  css  js  c++  java
  • 最长回文子序列(不连续)以及最长回文子串(连续)

    整理了一下关于回文子序列和回文子串的程序。

    其中(1)和(2)是采用动态规划的思想写出的回文子序列的程序,这种子序列就是在原始的串中可以不连续,比如对于那种要求删除几个字符来得到最长的回文字符串的题就是这种情况。

    比如caberbaf.  最长的子序列是5 abeba 或者abrba。而子串最长只有1

    (3)(4)(5)都是最长子串的求法。(3)是暴力求解,(4)是改进的暴力求解。(5)采用的是动态规划的方法。

      1 #include <iostream>
      2 #include <string>
      3 #include <vector>
      4 #define MAX 1000
      5 using namespace std;
      6 
      7 /***************************************************************************************/
      8 /***************************************************************************************/
      9 
     10 /*(1)采用循环
     11 最长回文子序列 (不连续地---序列,子串是连续地)
     12 动态规划
     13 **/
     14 int maxPalindromeLen(string s){
     15     int len = s.length();
     16     if (len == 0)
     17     {
     18         return 0;
     19     }
     20     else if (len == 1)
     21     {
     22         return 1;
     23     }
     24     vector<int> max_Palind(len);
     25     //init
     26     for (size_t i = 0; i < len; i++)
     27     {
     28         max_Palind[i] = 0;
     29     }        
     30     max_Palind[0] = 1;
     31 
     32     for (int j = 0; j < len; j++)
     33     {
     34         for (int i = 0; i <j; ++i)
     35         {
     36             if (max_Palind[i]<max_Palind[i + 1] + (s[i] == s[j]) * 2){
     37                 max_Palind[i] = max_Palind[i + 1] + (s[i] == s[j]) * 2;
     38             }
     39         }
     40         max_Palind[j] = 1;
     41     }
     42     return max_Palind[0];
     43 }
     44 
     45 /***************************************************************************************/
     46 /***************************************************************************************/
     47 int max(int a, int b)
     48 {
     49     if (a > b)
     50     {
     51         return a;
     52     }
     53     else
     54     {
     55         return b;
     56     }
     57 
     58 }
     59 /*(2) 采用递归
     60 最长回文子序列 (不连续地---序列,子串是连续地)
     61 最优子结构
     62 假设 X[0 ... n-1]  是给定的序列,长度为n.  让 L(0,n-1) 表示 序列 X[0 ... n-1] 的最长回文子序列的长度。
     63 
     64 1. 如果X的最后一个元素和第一个元素是相同的,这时:L(0, n-1) = L(1, n-2) + 2 , 
     65 还以 “BBABCBCAB” 为例,第一个和最后一个相同,因此 L(1,n-2) 就表示蓝色的部分。
     66 
     67 2. 如果不相同:L(0, n-1) = MAX ( L(1, n-1) ,  L(0, n-2) )。 
     68 以”BABCBCA” 为例,L(1,n-1)即为去掉第一个元素的子序列,L(0, n-2)为去掉最后一个元素。
     69 */
     70 int lps(string &s, int i, int j)
     71 {
     72     if (i == j)
     73     {
     74         return 1;
     75     }
     76     if (i > j)
     77     {
     78         return 0;
     79     }
     80     //如果首尾相同
     81     if (s[i] == s[j])
     82     {
     83         return lps(s, i + 1, j - 1) + 2;
     84     }
     85     //首尾不同,两种情况
     86     return max(lps(s, i + 1, j), lps(s, i, j - 1));
     87 }
     88 
     89 /***************************************************************************************/
     90 /***************************************************************************************/
     91 
     92 /*(3)最长回文子串(就是连续地)
     93 暴力循环
     94 */
     95 bool isPalindrome(string s)
     96 {
     97     int len = s.size();
     98     for (int i = 0; i < len / 2; i++)
     99     {
    100         if (s[i] != s[len - i - 1])
    101         {
    102             return false;
    103         }
    104     }
    105     return true;
    106 }
    107 int maxPalindromeLength(string s)
    108 {
    109     int len = s.size();
    110     int maxLength = 0;
    111     for (int i = 0; i < len - 1; i++)
    112     {
    113         for (int j = 1; j <= len - i; j++)
    114         {
    115             //构造一个子串,从i开始的j个字符
    116             string substr = s.substr(i, j);
    117             if (isPalindrome(substr))
    118             {
    119                 int len = substr.size();
    120                 if (len > maxLength)
    121                 {
    122                     maxLength = len;
    123                 }
    124             }
    125         }
    126     }
    127     return maxLength;
    128 }
    129 
    130 /***************************************************************************************/
    131 /***************************************************************************************/
    132 
    133 /*(4)改进的最长回文子串(o(n的平方))
    134 以中心轴进行判断
    135 */
    136 int l2r(string s,int mid)
    137 {
    138     int l = mid - 1, r = mid + 1;
    139     int len = s.size();
    140     while (s[mid] == s[r])//考虑那种中间相同的情况 比如abbc 相当于bb为中心
    141     {
    142         r++;
    143     }
    144     while (l >= 0 && r < len && s[l] == s[r])
    145     {
    146         l--;
    147         r++;
    148     }
    149     return r - l - 1;
    150 }
    151 int maxl2r(string s)
    152 {
    153     int len = s.size();
    154     if (len == 0)
    155     {
    156         return 0;
    157     }
    158     else if (len == 1)
    159     {
    160         return 1;
    161     }
    162     int maxlength = 0;
    163     for (int i = 0; i < len; i++)
    164     {
    165         int len = l2r(s, i);
    166         if (maxlength < len)
    167         {
    168             maxlength = len;
    169         }
    170     }
    171     return maxlength;
    172 }
    173 
    174 /***************************************************************************************/
    175 /***************************************************************************************/
    176 
    177 /*(5)以动态规划的方法解决最长回文子串(连续地)
    178 递推式表示在s[i] = s[j]情况下,如果s[i+1..j-1]是回文子串,则s[i..j]也是回文子串;
    179 如果s[i+1..j-1]不是回文子串,则s[i..j]也不是回文子串。
    180 
    181 初始状态:
    182 
    183 c[i][i] = 1
    184 c[i][i+1] = 1 if s[i] == s[i+1]
    185 */
    186 int maxDynamicLength(string s)
    187 {
    188     int len = s.size();
    189     if (len == 0)
    190     {
    191         return 0;
    192     }
    193     else if (len == 1)
    194     {
    195         return 1;
    196     }
    197 
    198     int i, length;
    199     int longest = 1;
    200     bool c[MAX][MAX] = {false};
    201     //init
    202     for (i = 0; i < len; i++)
    203     {
    204         c[i][i] = true;
    205     }
    206     for (int i = 0; i < len - 1; i++)
    207     {
    208         if (s[i] == s[i + 1])
    209         {
    210             c[i][i + 1] = true;
    211             longest = 2;
    212         }
    213     }
    214 
    215     //上面已经解决了2个字符的情况;下面从字符长度为3开始
    216     for (length = 3; length <= len; length++)
    217     {
    218         for (i = 0; i < len - length + 1; i++)
    219         {
    220             int j = i + length - 1;//i是字符起点索引 j是终止索引
    221             if (s[i] == s[j] && c[i+1][j-1])
    222             {
    223                 c[i][j] = true;
    224                 longest = length;
    225             }
    226         }
    227     }
    228     return longest;
    229 }
    230 string longestPalindromeDP(string s) {
    231     int n = s.length();
    232 
    233     int longestBegin = 0;
    234 
    235     int maxLen = 1;
    236 
    237     bool table[1000][1000] = { false };
    238 
    239     for (int i = 0; i < n; i++) {
    240 
    241         table[i][i] = true;   //前期的初始化
    242 
    243     }
    244 
    245     for (int i = 0; i < n - 1; i++) {
    246 
    247         if (s[i] == s[i + 1]) {
    248 
    249             table[i][i + 1] = true; //前期的初始化
    250 
    251             longestBegin = i;
    252 
    253             maxLen = 2;
    254 
    255         }
    256 
    257     }
    258 
    259     for (int len = 3; len <= n; len++) {
    260 
    261         for (int i = 0; i < n - len + 1; i++) {
    262 
    263             int j = i + len - 1;
    264 
    265             if (s[i] == s[j] && table[i + 1][j - 1]) {
    266 
    267                 table[i][j] = true;
    268 
    269                 longestBegin = i;
    270 
    271                 maxLen = len;
    272 
    273             }
    274 
    275         }
    276 
    277     }
    278 
    279     return s.substr(longestBegin, maxLen);
    280 
    281 }
    282 
    283 /***************************************************************************************/
    284 /***************************************************************************************/
    285 
    286 int main(int args, char* argv[])
    287 {
    288     string s;
    289     while (cin >> s)
    290     {
    291         int len = s.size() - 1;
    292         cout << maxPalindromeLength(s) << endl;
    293         //cout << lps(s, 0, len) << endl;
    294         //cout << maxl2r(s) << endl;
    295         //cout << maxDynamicLength(s) << endl;
    296         //string substr = longestPalindromeDP(s);
    297         //cout << substr << ":" << substr.size() << endl;
    298     }
    299     return 0;
    300 }
  • 相关阅读:
    我的收藏:第一章:汇总
    实战:第二章:关于EZDML工具使用踩的坑
    Docker:第二章:部署项目,对镜像,容器的操作
    电商网站项目:第一章:进度
    多线程:第一章:我(线程)这一生
    性能优化:第一章:我们应该怎么优化
    关于EZDML数据库表结构制作设计工具使用踩的坑
    集群与分布的区别
    strip_tags--php
    关于html的一些杂技
  • 原文地址:https://www.cnblogs.com/leewhite/p/5354491.html
Copyright © 2011-2022 走看看