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

    最长回文子串一般有以下两种情况:

    问题描述1:给定一个字符串,求它的最长回文子串的长度,并且回文子串的字符在原字符串中必须连续。

    分析:很明显可以使用暴力法求解,枚举出所有的子串,分别判断其是否为回文。但是这种方法效率比较低,而且时间复杂度太高,并且如果一个长的子串包含另一个短一些的子串,那么对子串的回文判断其实是不需要的,等等。

            我们可以对其进行优化,因为回文串是以中间的字符为中心左右对称的,例如回文串“aba”,以b为中心,它的左端和右端对称,都是a。

            所以我们可以枚举中心位置,从中心位置向两边扩展,记录并更新得到的最长的回文长度。这里要注意回文串的长度是计数还是偶数,因此需要分别进行讨论。

            具体的Java代码如下,语句都很通用,读者可以很容易的转换为其他语言:

            

     1 import java.util.*;
     2  class Test {
     3       public static int maxhuiwenlength(StringBuilder str){
     4           if(str.length()==0)return 0;                   //如果长度为空字符串,直接返回0
     5           int i,j,max=0,p;                               //max记录最长的长度
     6           int n=str.length();                            //求字符串长度
     7           for(i=0;i<n;i++)
     8           {
     9               for(j=0;(i-j)>=0 && (i+j)<n;j++)           //假设长度为奇数的回文串
    10                   if(str.charAt(i-j)!=str.charAt(i+j))break;
    11               p=(j-1)*2+1;
    12               if(p>max)max=p;
    13               for(j=0;(i-j)>=0 && (i+j+1)<n;j++)         //假设长度为偶数的回文串
    14                   if(str.charAt(i-j)!=str.charAt(i+j+1))break;
    15               p=(j-1)*2+2;
    16               if(p>max)max=p;
    17           }  
    18           return max;                                   //返回回文串长度
    19       }        
    20     }
    21  
    22 public class Main {
    23     public static void main(String[] args) {
    24       StringBuilder str=new StringBuilder("123458"); 
    25      System.out.print("字符串:"+str+"的最大回文子串长度为:"+Test.maxhuiwenlength(str));
    26     }
    27 
    28 }
    View Code

    问题描述2:给定一个字符串,求它的最长回文子串的长度,并且回文子串的字符在原字符串中可以不连续。也就是说可以删除原字符串中的一个或多个字符。

    分析:该问题与问题1相比,有了一定的难度,难度在于可以删除原字符串中的字符,但是基本思想还是和问题1一样,需要在问题1上做一些改进。

            同样需要分别考虑回文串是奇数还是偶数,无论哪种情况,都遵循这个过程。

                      当扫描到两端字符相等时,两端都要扩展,如果不相等,则要分两步进行:

                                                                                                                第一步,固定右端,向左扫描一遍,如果发现相等,则两端同时扩展,长度加2.否则左指针-1

                                                                                                                第二步,固定左端,向右扫描一遍,如果发现相等,则两端同时扩展,长度加2.否则右指针+1

             具体的Java代码如下,代码写法比较通用,读者可以很容易转换为其他语言。

     1 import java.util.*;
     2  class Test {
     3       public static int maxhuiwenlength(StringBuilder str){
     4           if(str.length()==0)return 0;                   //如果长度为空字符串,直接返回0
     5           int i,j,max=0,p;                               //max记录最长的长度,p记录临时最长长度
     6           int n=str.length();                            //求字符串长度
     7           int low,high;                                  //两个指针分别指向两端
     8           for(i=1;i<n;i++)
     9           {   
    10               p=1;                                      //寻找以i为中心的奇数长度的回文,最少长度也为1
    11               low=i-1;high=i+1;
    12               while(low>=0 && high<n)
    13               {
    14                   if(str.charAt(low)==str.charAt(high))   //如果两端相等,两端同时扩展,长度加2
    15                       {
    16                         low--;
    17                         high++;
    18                         p=p+2;                            
    19                       }
    20                   else{                                  //如果两端不相等
    21                       int t=low;
    22                       while(--low>=0 && high<n)          //右端固定不变,向左扫描一遍
    23                           if(str.charAt(low)==str.charAt(high))  //扫描到相等时,两边同时扩展,长度加2
    24                           {
    25                               high++;
    26                               p=p+2;
    27                           }
    28                       low=t;
    29                       while(low>=0 && ++high<n)          //左端固定不变,向右扫描一遍
    30                           if(str.charAt(low)==str.charAt(high))     //扫描到相等时,两边同时扩展,长度加2
    31                           {
    32                               low--;
    33                               p=p+2;
    34                           }
    35                   }
    36               }
    37               if(p>max)max=p;                          //更新最长长度
    38               
    39               p=0;                                     //寻找以i-1,i为中心的偶数长度的回文
    40               low=i-1;high=i;
    41               while(low>=0 && high<n)
    42               {
    43                   if(str.charAt(low)==str.charAt(high))       //如果两端相等,两端同时扩展,长度加2
    44                       {
    45                         low--;
    46                         high++;
    47                         p=p+2;
    48                       }
    49                   else{
    50                       int t=low;
    51                       while(--low>=0 && high<n)                     //右端固定不变,向左扫描一遍
    52                           if(str.charAt(low)==str.charAt(high))     //扫描到相等时,两边同时扩展,长度加2
    53                           {
    54                               high++;
    55                               p=p+2;
    56                           }
    57                       low=t;
    58                       while(low>=0 && ++high<n)                     //左端固定不变,向右扫描一遍
    59                           if(str.charAt(low)==str.charAt(high))     //扫描到相等时,两边同时扩展,长度加2
    60                           {
    61                               low--;
    62                               p=p+2;
    63                           }
    64                   }
    65               }
    66               if(p>max)max=p;                           //更新最长长度
    67           }  
    68           if(max==0)max=1;                              //因为只要字符串不为空,回文串最少也为1
    69           return max;                                   //返回回文串长度
    70       }        
    71     }
    72  
    73 public class Main {
    74     public static void main(String[] args) {
    75       StringBuilder str=new StringBuilder("123251"); 
    76      System.out.print("字符串:"+str+"的最大回文子串长度为:"+Test.maxhuiwenlength(str));
    77     }
    78 
    79 }
    View Code
  • 相关阅读:
    [atARC088F]Christmas Tree
    [atARC109F]1D Kingdom Builder
    [luogu4259]寻找车位
    [atARC087F]Squirrel Migration
    [atARC087E]Prefix-free Game
    [atARC110F]Esoswap
    [atARC110E]Shorten ABC
    [atARC084D]Small Multiple
    [atARC083F]Collecting Balls
    [hihocoder][Offer收割]编程练习赛49
  • 原文地址:https://www.cnblogs.com/guozhenqiang/p/5430445.html
Copyright © 2011-2022 走看看