【LeetCode】5. Longest Palindromic Substring最大Palindromic字符串|DP动态规划

5. Longest Palindromic Substring

Given a string s, find the longestpalindromic substring in s. You may assume that the maximum lengthof s is 1000.

Example:

Input: "babad"

 

Output: "bab"

 

Note: "aba" is also a valid answer.

Example:

Input: "cbbd"

 

Output: "bb"

 

//问题通过样例输入输出已经很明白了,如果一个字符串从左向右写和从右向左写是一样的,这样的字符串就叫做palindromic string,如aba,或者abba。本题是这样的,给定输入一个字符串,要求输出一个子串,使得子串是最长的padromicstring。

【解法一】

So:下列解法是的时间复杂度为O(N*N*N)

vector<int> vec1 ={0,2};

vector<int> vec2={1};

map[a]=vec1;

map[b]=vec2.

这样,完成了第一步,构造好了一个map,储存了原字符串中,各个字符出现的位置了。

现在进行第二步,从头到尾再扫描一遍字符串,根据map中储存的位置,很容易找到候选子串了。

class Solution {

public:

   string longestPalindrome(string s) {

       int n=s.length();

       if(n==0)return "";

       if(n==1)return s;

       string c_string="";

       string l_string="";

       int c_l=0,l_l=0;

       map<string,vector<int>> s_map;

       for(int i=0;i<n;i++){

           map<char,vector<int>>::iterators_map_t=s_map.find(char(s[i]));

           if(s_map_t==s_map.end())//没有查找到

           {

                vector<int>pos;

                pos.push_back(i);

               s_map.insert(pair<char,vector<int>>(char(s[i]),pos));

           }else{

                vector<int>&pos=s_map_t->second;

               pos.push_back(i);

           }

       }//以上构建了一个map

       for(int index=0;index<s.length();index++){

            map<char,vector<int>>::iterators_map_t2=s_map.find(s[index]);

           if(s_map_t2->second.size()==1){

                c_l=1;

                c_string=s[index];

                if(c_l>l_l){

                    l_l=c_l;

                    l_string=c_string;

                }

           }else{

                vector<int>&it=s_map_t2->second;

                int it_num=it.size();

                int head=index;

                for(intj=(it_num-1);j>=0;--j){

                    head=index;

                    int t=it[j];

                    if(t<head)continue;

                    c_l=t-head+1;

                    if(c_l<l_l||c_l==0)continue;

                    c_string=substr(head,t);

                   while(((t-head)>=1)&&(c_string[head]==c_string[t])){

                        head++;

                        t--;

                    }

                    if((t-head)=-1||(t-head)==0){

                        l_l=c_l;

                        l_string=c_string;

                    }

                   

                }

           }

       }

       return l_string;

    }

};

遗留问题:Your answer

Line12: no matching function for call to'std::map<std::__cxx11::basic_string<char>, std::vector<int>>::find(__gnu_cxx::__alloc_traits<std::allocator<char>>::value_type)'

【解法二】动态规划DP(时间复杂度N*N)

首先,写出动态转移方程。

Define P[ i, j ] ← true iff the substring Si …Sj is a palindrome, otherwise false.

P[ i, j ] ← ( P[ i+1, j-1 ] and Si = Sj ) ,显然,如果一个子串是回文串,并且如果从它的左右两侧分别向外扩展的一位也相等,那么这个子串就可以从左右两侧分别向外扩展一位。

其中的base case是

P[ i, i ] ← true

P[ i, i+1 ] ← ( Si = Si+1 )

然后,看一个例子。

假设有个字符串是adade,现在要找到其中的最长回文子串。使用上面的动态转移方程,有如下的过程:

按照红箭头->黄箭头->蓝箭头->绿箭头->橙箭头的顺序依次填入矩阵,通过这个矩阵记录从i到j是否是一个回文串。

最后, 看code。

class Solution {

public:

   string longestPalindrome(string s) {

       int n=s.length();

       int l=0;

       int max=1;

       bool table[1000][1000]={false};

       for(int i=0;i<n;i++){

           table[i][i]=true;

       }

       for(int i=0;i<n-1;i++){

           if(s[i]==s[i+1]){

                table[i][i+1]=true;

                l=i;

                max=2;

           }

       }

       for(int len=3;len<=n;len++){

           for(int i=0;i<n-len+1;i++){

                int j=i+len-1;

               if(table[i+1][j-1]&&s[i]==s[j]){

                    table[i][j]=true;

                    l=i;

                    max=len;

                }

           }

       }

       return s.substr(l,max);

    }

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值