• Longest Palindromic Substring问题


    Longest Palindromic Substring问题

    1.题目描述

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

    Example:
    Input: "babad"
    Output: "bab"
    Note: "aba" is also a valid answer.//aba也是有效的答案
    
    Example:
    Input: "cbbd"
    Output: "bb"
    

    给定一个字符串s,找到当中的最长回文子串。你可能需要假设s的最大长度是1000。

    这里解释一下回文串的定义:
    “回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。

    题目中的回文子串就是满足回文串性质的最长子串。

    2.解题思路

    看到这道题的时候,第一个想法就是暴力解法,扫描以每个字符串为中心的回文串,在其中找到最长的那个回文子串,就可以的出结果,这中思路没有什么技巧,比较好想,代码也比较好写,但是边界问题还有一些细节需要注意:

    1. 当字符串为空或者只有一个的情况。
    2. 遇到第一个字符和最后一个字符的时候怎么处理。
    3. aba和abba情况的区分。
      这是最简单也是最笨的解决这种问题的思路,在discuss里面有更好的解决办法,能把复杂度降到O(n)的神奇算法,我根据算法实现了代码,但是超时了,好无奈。这里给出一个博客,总结了这道题的各种解法:
      博客地址,还有一篇专门介绍这种方法的博客

    3.代码

    1. class Solution
    2.  
    3. public String test(String s,int l,int r)
    4. int n = s.length(); 
    5. while(l>=0 && r<=n-1 && s.charAt(l)==s.charAt(r)) { 
    6. //限定l和r的范围,并比较是否相等,相等就对范围进行扩张。 
    7. l--; 
    8. r++; 

    9. return s.substring(l+1, r); 
    10. //这里就要仔细 考虑边界情况以及当自己和自己比较的时候 
    11. //l--,但是可能存在下个不满足条件,而substring函数是不包括r这个边界的 

    12. public String longestPalindrome(String s)
    13. int slen = s.length(); 
    14. if(slen==0
    15. return null;//若字符串为空 
    16. //int[] p = new int[slen]; 
    17. String longString = "";//新建一个空的字符串 
    18. for(int i=0;i<slen;i++) { 
    19. String p1= test(s,i,i+1);//这种情况是对于abba这种中间有重复的情况,是偶数 
    20. String p2 = test(s,i,i);//这种情况对应于aba这种情况,是奇数 
    21. if(p1.length()>p2.length()) {//获得当前的最大回文串 
    22. longString = longString.length()>p1.length()? longString:p1; 

    23. else 
    24. longString = longString.length()>p2.length()? longString:p2; 

    25. return longString; 

    26.  

    下面是leetcode上排名前几的代码,它的基本思路也是查找以每个字符为中心的回文串,但是它优化了碰到重复字符时的情况:

    1. class Solution
    2. private int max_length; 
    3. private int start; 
    4.  
    5. public String longestPalindrome(String s)
    6. if(s.length() < 2
    7. return s; 
    8. for(int i = 0; i < s.length();) { 
    9. i = extendPalindrome2sides(s, i); 

    10. return s.substring(start, start + max_length); 

    11.  
    12. private int extendPalindrome2sides(String s, int anchor)
    13. //Skip duplicate characters. 
    14. int j = anchor, k = anchor; 
    15. while(k < s.length() - 1 && s.charAt(k) == s.charAt(k + 1)) k++; 
    16. //这句代码跳过了重复字符,也就是处理了偶数的那种情况 
    17. //当是奇数的时候,不会进入循环 
    18. int next_i = k + 1;//计算出下一个需要进行回文计算的字符 
    19.  
    20. while(j >= 0 && k < s.length() && s.charAt(j) == s.charAt(k)) { 
    21. j--; 
    22. k++; 

    23. int cur_leng = (--k) - (++j) + 1
    24. //这个--k和++j,理解起来有点模糊,但是写的很优雅 
    25. //还是想到边界情况:当最后一个不满足的时候,但是index已经定位到它们, 
    26. //这就需要把左边还原 
    27. if(cur_leng > max_length) { 
    28. start = j; 
    29. max_length = cur_leng; 

    30.  
    31. return next_i; 


    传说中的马拉车算法:

    1. public static String longestPalindrome1(String s)
    2. if(s.length()==0
    3. return null
    4. String tmp = "$#"
    5. for(int i= 0;i<s.length();i++) { 
    6. tmp+=s.charAt(i); 
    7. tmp+="#"

    8. tmp+="^"
    9. int [] p=new int[tmp.length()]; 
    10.  
    11. int c = 0,r=0,len=0,cen=0
    12. for(int i=1;i<tmp.length()-1;i++) { 
    13. p[i] = r>i? Math.min(p[2*c-i],r-i):1
    14. while(tmp.charAt(i-p[i])==tmp.charAt(i+p[i])) 
    15. p[i]++; 
    16. if(r<i+p[i]) { 
    17. r=i+p[i]; 
    18. c=i; 

    19. if(p[i]>len) { 
    20. len=p[i]; 
    21. cen = i; 


    22. int pos =(cen-len)/2
    23. return s.substring(pos, pos+len-1); 
    24.  

  • 相关阅读:
    oracle内核参数详解
    oracle分区表原理学习
    expdp导出时报错ora-16000
    【CS224n-2019学习笔记】Lecture 1: Introduction and Word Vectors
    【SQL必知必会笔记(3)】SELECT语句的WHERE子句数据过滤操作
    【SQL必知必会笔记(2)】检索数据、排序检索数据
    【SQL必知必会笔记(1)】数据库基础、SQL、MySQL8.0.16下数据库、表的创建及数据插入
    win10,64位操作系统安装mysql-8.0.16经验总结(图文详细,保证一次安装成功)
    【机器学习实战笔记(3-3)】关于朴素贝叶斯实现代码中的一些错误总结
    【机器学习实战笔记(3-2)】朴素贝叶斯法及应用的python实现
  • 原文地址:https://www.cnblogs.com/chailinbo/p/7445547.html
Copyright © 2020-2023  润新知