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

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"
这个博客说的很好,很优秀,解法全面,有空应该看下
https://www.cnblogs.com/grandyang/p/4464476.html

解法:
主要需要注意的就是:一般根据左右计算距离的时候,不要被左右这个字眼迷惑,真正理解在实际中的位置含义,尤其是这种左右变量本身也在
循环中迭代,数值不断变化,有可能出问题
2plus:
when look tutorial,attention to < <= whether have = important than number.
Maybe make some change to make sure some variable change,please remeber to change it back
BONUS:
left right is just a represent for calculation.Pay attention to its real meaning.If it's really
the left and right.if it need +-1 to represent the real meaning
Be good at using &
when we want to let a function change variable value instead of global variable use & to change it
is a good choice
#include <iostream>
#include <algorithm>
#include<string>
using namespace std;

class Solution
{
public:
    string longestPalindorme(string s)
    {
        if(s.size()<2) return s;
        int n=s.size(),maxLen=0,start=0;
        //ATTENTION:this range should be n-1,because this is i+1 at below,if <n out of range,if want from 1->n need i-1,i this combination
        for(int i=0;i<n-1;++i)i-1
        {
            //为了对比奇数和偶数回文
            SearchPalindorm(s,i,i,start,maxLen);
            SearchPalindorm(s,i,i+1,start,maxLen);

        }
         cout<<"start:"<<start<<"maxLen:"<<maxLen<<endl;
        return s.substr(start,maxLen);

    }

    void SearchPalindorm(string s,int left,int right,int& start,int& maxLen)
    {
        while(left>=0&&right<s.size()&&s[left]==s[right])
        {
            --left;
            ++right;
        }
        //这里真的很反套路:本身看到left和right都能意识到right-left+1才是长度,但这里只有当left和right不符合情况的时候才会退出循环,即此时的left和right都是被多加和间了一次的,所以真实情况是(right-1)-(left+1)+1最后拆开就是下面的情况
        if(maxLen<right-left-1)
        {
            start=left+1;
            maxLen=right-left-1;
        }
        

    }
};


int main()
{
    Solution s;
    string si,so;
    //cin>>si;
    si="abbad";
    so=s.longestPalindorme(si);

    cout<<so<<endl;
    return 0;
}

Change the above-mentioned method,use Pruning operation save time use jump duplicate character divide operate odd and even situation.very quick and save space method.show as below:

 

#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
#include<iomanip>
#include<vector>
#include<list>
#include<queue>
#include<algorithm>
#include<stack>
#include<map>
using namespace std;
class Solution {
public:
    string longestPalindrome(string s) {
        //special case
        if(s.size()<2) return s;
        //stop early&jump duplicate
        int n=s.size(),maxLen=0,start=0;
        for(int i=0;i<n;)
        {
            //Pruning operation make code faster
            if(n-i<maxLen/2) break;
            int left=i,right=i;
            //solve odd and even if even jump its duplicate center
            while(right<n-1&&s[right]==s[right+1])
            {
                right++;
            }
            //replace i++'s function
            i=right+1;
            //ATTENTION:use left-1&right+1 compare if equal then execute operation,guarantee variable represent actual value
            while(left-1>=0&&right+1<n&&s[left-1]==s[right+1])
            {
                left--;
                right++;
            }
            if(right-left+1>maxLen)
            {
                maxLen=right-left+1;
                start=left;
            }
        }
        //function has different usage in different language,in C++ substr means start and length
        return s.substr(start,maxLen);

    }
};

int main()
{
    Solution s1;
    cout<<s1.longestPalindrome("an0naw")<<endl;
    return 0;
}

 

 

 

After such a long term finally get in charge of this function Manacher:

this is the method I solved by myself,At first,it appear  a problem is index calculate error,so just an example can make it clear

 

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # preaction
        s="#"+"#".join(s)+"#"
        # print(s)
        # initialization
        maxR=0
        maxL=0
        pos=0
        poss=0
        p=[0]*len(s)
        # for loop initial p
        for i in range(len(s)):
            p[i]=min(p[int(pos*2-i)],maxR-i) if i<maxR else 1

            while i+p[i]<len(s) and i-p[i]>=0 and s[i+p[i]]==s[i-p[i]]:
                p[i]+=1

            if maxR<i+p[i]:
                maxR=i+p[i]
                pos=i

            if maxL<p[i]:
                maxL=p[i]
                poss=i
        # print(maxL)
        # print(poss)
        # s_res=""
        s_res=s[poss-maxL+1:poss+maxL-1]
        return s_res.replace("#","")
        # print("fa")
        # print(s_res)
        # print("fb")
        # print(s_res.replace("#",""))

solu=Solution()
print(solu.longestPalindrome(s="annaw"))

 311908update structure has progess

late problem be solved:

i+p[i] i-p[i] needn't -1 +1 because if p[i]==1 it will count i twice to compare it with i itself

directly plus and minus won't have this problem

 

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # preaction
        s='#'+'#'.join(s)+'#'
        # print(s)

        # initial
        MaxR=0
        MaxL=0
        pos=0
        ppos=0
        p=[0]*len(s)

        # judge
        for i in range(len(s)):
            p[i]=min(MaxR-i,p[2*pos-i]) if i<MaxR else 1

            # addition analyse
            while i+p[i]<len(s) and i-p[i]>=0 and s[i+p[i]]==s[i-p[i]]:
                p[i]+=1

            # update
            if MaxR<i+p[i]:
                MaxR=i+p[i]
                pos=i

            if MaxL<p[i]:
                MaxL=p[i]
                poss=i

        p_res=s[poss-MaxL+1:poss+MaxL-1]
        return p_res.replace('#','')

 C++ version:

in C++ solution,need add extra character before string,because C++ don't have replace function like python,so the answer cannot show as changed string but original string.So it need to find corresponding relationship between orginal and replaced one

ATTENTION point:

C++/Python cannot directly plus character to string array,so new a new string is very important.But python has function join can directly use "#".join(s) add "#" between string.

use new name such as nfinal easy to miss with n,maybe cause error.

#include<iostream>
#include<string>
using namespace std;
class Solution {
public:
    string longestPalindrome(string s) {
        //pre-action
        int n=s.size();
        string trans="$#";
        for(int i=0;i<n;i++)
        {
            trans+=s[i];
            trans+="#";
        }
        int nfinal=trans.size();
        //initialize
        int MaxR=0;int posR=0;
        int MaxL=0;int posRes=0;

        int len[nfinal]={0};
        //judge
        for(int i=0;i<nfinal;i++)
        {
            len[i]=i<MaxR?min(len[2*posR-i],MaxR-i):1;

            while(i+len[i]<nfinal&&i-len[i]>=0&&trans[i+len[i]]==trans[i-len[i]])
            {
                len[i]++;
            }

            //compare
            if(len[i]>MaxL)
            {
                MaxL=len[i];
                posRes=i;
            }

            if(i+len[i]>MaxR)
            {
                MaxR=len[i]+i;
                posR=i;
            }

        }
        //deal result
        //cout<<"p"<<posRes<<"M"<<MaxL<<endl;
        return s.substr((posRes-MaxL)/2,MaxL-1);
    }
};
int main()
{
    Solution s1;
    string s="annaw";
    cout<<s1.longestPalindrome(s)<<endl;
    return 0;
}

 DP method use array to store flag whether j to i(j<i) is a palindrome string,use recursion formula.

But time and space just only 3,40% opponents were defeated.

code please remeber to initialize len as 1,or it will cause problem when example like {ac} this not duplicate example

ALSO don't forget DEALSPECIAL CASE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
#include<iomanip>
#include<vector>
#include<list>
#include<queue>
#include<algorithm>
#include<stack>
#include<map>
using namespace std;
class Solution {
public:
    string longestPalindrome(string s) {
        //special case operation don't forget
        if(s.empty()) return "";
        if(s.size()==1) return s;
        //array method
        int n=s.size();
        //must initialize to 1,on one way there must minimum this value would be 1,on the other,if example like ac this not have duplicate number while not operate calculation
        int arr[n][n]={0},left=0,len=1;
        for(int i=0;i<n;i++)
        {
            arr[i][i]=1;
            for(int j=0;j<i;j++)
            {
                arr[j][i]=((s[i]==s[j])&&(i-j<2||arr[j+1][i-1]));

                if(arr[j][i]&&(i-j+1>len))
                {
                    len=i-j+1;
                    left=j;
                }
            }
        }
        return s.substr(left,len);
    }
};
int main()
{
    Solution s1;
    cout<<s1.longestPalindrome("ac")<<endl;
    return 0;
}

 

6. ZigZag Conversion

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:

P     I    N
A   L S  I G
Y A   H R
P     I
#coding=utf-8
class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        length = len(s)  #总共有多少元素
        step = 2*numRows-2      #有几列, 2n-2 = 0+(n-1)+(n-2)+1
        
        if s == "":      #如果空字符串,返回空字符串""
            return ""
        if length<numRows or numRows ==1 :       #如果只有一行,则直接返回原字符串
            return s
        result = s[::step] #这是第一行,他通过切片的步进step来取值,因为每个元素都是间隔一个step
                          #这题里面,首行和尾行是特殊的,所以要区别对待
        for i in range(1,numRows-1):  #开始迭代除了第一行和最后一行之外的中间所有行
            for j in range(i,length,step): #这里关键的地方,他将图形在纵向上进行切割,以每个step为标准开头,进行迭代
                result += s[j]        #在每次切割后,进行添加的第一个元素,应该是每一行的开头的元素加上某倍数的step
                if j+(step-i*2) < length:  #如果斜线上的元素是在总长度以内的
                    result += s[j+step-i*2] #那么,就添加此元素
        result += s[numRows-1::step] #最后一行开始迭代        
        print (result)
        return result

 

 C++ version:
Special case always need to be handle firstly to inprove performance
#include<bits/std++.h>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
class Solution {
public:
    string convert(string s, int numRows) {
     //easy forget
     if(numRows==1) return s;
vector
<string> ss(numRows); int n=s.length(); int i=0,f=0; bool down=true; while(i<n) { // if(down) { ss[f]+=s[i]; f++; if(f==numRows) { f-=2; down=false; } } else { ss[f]+=s[i]; f--; if(f==-1) { f=1; down=true; } } i++; } string ans; for(auto t:ss) { ans+=t; } return ans; } }; int main() { Solution s1; string s="PAYPALISHIRING"; int numRows=3; string ans; ans=s1.convert(s,numRows); cout<<ans<<endl; string res="PINALSIGYAHRPI"; return 0; }

 

 

 

posted on 2019-06-08 23:45  黑暗尽头的超音速炬火  阅读(188)  评论(0编辑  收藏  举报