zoukankan      html  css  js  c++  java
  • 【Leetcode】Longest Palindromic Substring

    问题:https://leetcode.com/problems/longest-palindromic-substring/

    给定一个字符串 S,求出 S 的最长回文子串

    思路:

    1. 回文:一个字符串从前和从后读一致。S = "ABBA"  从前读:ABBA,从后读:ABBA

    2. 最简单的做法:列出所有的子串,并判断是否是回文,从中找出最长的。

      表格列出了所有的子串,第 i 行是以 S 的第 i 个字符开始的子串。S = "ABBA"

     1  A  AB  ABB  ABBA
     2      B    BB    BBA
     3          B      BA
     4              A

     从最后一行往上,可以看到他们的共同部分,用红色标出。共同的子问题~动态规划。

    3. 动态规划,自底向上求解问题 

      1) 对子问题的结果进行存储和表示

      len[i]:包含S[i] 的最长回文子串的长度

      all[i]:S 的后半部分S[i, ..., n - 1] 中的最长回文子串长度 

      2) 把子问题的结果合并成它的上一层

       子问题比它的上一层增加了一个字符。已经求得 S[i+1, ...] 子问题的解:从S[i+1]开始有len[i+1]长的回文子串 S[i+1]~S[n], all[i+1]

       

      ** 如果S[i]和这个子串的后一个字符一样,则从S[i]开始的回文子串可以包含它

      比如:S="ABBA",已知 len[1] = 2,S[0]=S[3]="A",所以len[0] = len[1]+2

      ** 反之,从S[i]开始的回文子串不可以包含它,则需要对该子串从两头开始遍历

          用两个变量分别从头 S[i] 和从尾S[n+1]开始比较,当发生不等的时候,就重新从头开始。

    源码 

     1 class Solution {
     2 public:
     3     string longestPalindrome(string s) {
     4         int ssize = s.length();
     5         int i, j, k, start;
     6         int* len = new int[ssize];
     7         int* all = new int[ssize];
     8         //初始化,最长为1
     9         len[ssize - 1] = all[ssize - 1] = 1;
    10         start = ssize - 1;
    11         
    12         for(i = ssize - 2; i >= 0; --i)
    13         {
    14             //计算len[i]
    15             if(i + len[i + 1] + 1 < ssize && s[i] == s[i + len[i + 1] + 1])//从S[i] 开始的回文子串包含S[i+1]开始的子串
    16                 len[i] = len[i + 1] + 2;
    17             else//反之需要遍历
    18             {
    19                 //j, k 表示从S[i] 开始可能的最长回文子串的区间
    20                 j = i;
    21                 k = i + len[i + 1];
    22                 while(j < k)
    23                 {
    24                     if(s[j] == s[k])
    25                     {
    26                         ++j;
    27                         --k;
    28                     }
    29                     else//两个字符不同时,j 需从头重新开始
    30                     {
    31                         j = i;
    32                         --k;
    33                     }
    34                 }
    35                 if(i == k && k == j)//
    36                     len[i] = 1;
    37                 else
    38                 {
    39                     len[i] = (k - i + 1) * 2;//子串长度为偶数
    40                     if(j == k)//子串长度为奇数
    41                       len[i]--;
    42                 }
    43             }
    44             //计算all[i]
    45             if(len[i] > all[i + 1])
    46             {
    47                 all[i] = len[i];
    48                 start = i;
    49             }
    50             else
    51             {
    52                 if(len[i] == all[i + 1])
    53                     start = i;
    54                 all[i] = all[i + 1];
    55             }
    56         }
    57         delete[] len;
    58         delete[] all;
    59         return s.substr(start, all[0]);
    60     }
    61 };
    View Code
  • 相关阅读:
    上下文切换
    NUMA的取舍与优化设置
    KVM CPU线程等学习记录
    openstack cpu pinning
    virt-install详解
    对KVM虚拟机进行cpu pinning配置的方法
    30 个 OpenStack 经典面试问题和解答
    OpenFace Docker 使用简介
    单链表、双链表及单链表的逆序
    Ubuntu14.04.1安装搜狗拼音输入法
  • 原文地址:https://www.cnblogs.com/coolqiyu/p/5597744.html
Copyright © 2011-2022 走看看