最长回文子串

30 篇文章 0 订阅
4 篇文章 0 订阅
/*
 * =====================================================================================
 *
 *       Filename:  Longest_Palindromic_Substring.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2013年01月10日 17时02分21秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Weidong Yang (cn), ywdong@mail2.sysu.edu.cn
 *        Company:  
 *
 * =====================================================================================
 */

/*
Given a string S, find the longest palindromic substring in S.
Hint:
First, make sure you understand what a palindrome means. A palindrome 
is a string which reads the same in both directions. For example, 
“aba” is a palindome, “abc” is not.
*/

#include <cstdio>
#include <cstdlib>
#include <string>  // for c++ string class
#include <fstream>
#include <sstream>
#include <iomanip>   
#include <iostream>  
#include <cstring> // for c str: strcmp,strcat
#include <cassert> // for assert()
#include <climits> // for INT_MIN, INT_MAX;

using namespace std;

bool dp[100][100];

/*
Dynamic programming solution, O(N2) time and O(N2) space:
To improve over the brute force solution from a DP approach, 
first think how we can avoid unnecessary re-computation in 
validating palindromes. Consider the case “ababa”. If we 
already knew that “bab” is a palindrome, it is obvious that 
“ababa” must be a palindrome since the two left and right 
end letters are the same.

Stated more formally below:

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

P[ i, j ] ← ( P[ i+1, j-1 ] and Si = Sj )
The base cases are:
P[ i, i ] ← true
P[ i, i+1 ] ← ( Si = Si+1 )
This yields a straight forward DP solution, which we first 
initialize the one and two letters palindromes, and work our 
way up finding all three letters palindromes, and so on… 
*/
char* LongestPalindromeDP(char* str)
{
    int n = strlen(str);
    if (n < 2)
        return str;

    int i,j,len;
    int begin = 0;
    int maxLen = 1;

    for (i = 0; i < 100; i++)
        for (j = 0; j < 100; j++)
            dp[i][j] = false;

    for (i = 0; i < n; i++)
        dp[i][i] = true;
    for (i = 0; i < n - 1; i++)
    {
        if (str[i] == str[i+1])
        {
            dp[i][i+1] = true;
            begin = i;
            maxLen = 2;
        }
    }

    for (len = 3; len <= n; len++)
    {
        for (i = 0; i <= n - len; i++)
        {
            j = i + len - 1;
            dp[i][j] = dp[i+1][j-1] && (str[i] == str[j]);
            if (dp[i][j] && len > maxLen)
            {
                begin = i;
                maxLen = len;
            }
        }
    }
   
    char* res = new char[maxLen+1];
    for (i = begin,j = 0; j < maxLen; i++,j++)
        res[j] = str[i];
    res[j] = '\0';

    return res;
}
/*
A simpler approach, O(N2) time and O(1) space:
In fact, we could solve it in O(N2) time without any extra space.

We observe that a palindrome mirrors around its center. Therefore, 
a palindrome can be expanded from its center, and there are only 
2N-1 such centers.

You might be asking why there are 2N-1 but not N centers? The reason 
is the center of a palindrome can be in between two letters. Such 
palindromes have even number of letters (such as "abba") and its 
center are between the two 'b's.

Since expanding a palindrome around its center could take O(N) time, 
the overall complexity is O(N2).
*/
void subString(char* src, char* dest, int begin, int len)
{
    if (begin < 0 || len < 0)
    {
        dest = '\0';
        return;
    }
    int i,j;
    for (i = begin, j = 0; j < len; i++, j++)
        dest[j] = src[i];
    dest[j] = '\0';
    return;
}

void ExpandCenter(char* src, char* dest, int left, int right)
{
    int l = left;
    int r = right;
    int n = strlen(src);
    while (l >= 0 && r < n && (src[l] == src[r]))
    {
        l--;
        r++;
    }
    // len = (r-1) - (l+1) + 1;
    subString(src, dest, l+1, r-l-1);
    return;
}

void LongestPalindromeSimple(char* src, char* dest)
{
    int n = strlen(src);
    if (n < 2)
    {
        dest = src;
        return;
    }
    char* tmp_dest = new char[n+1];
    unsigned int maxLen = 1;
    subString(src, dest, 0, 1);
    
    for(int i = 0; i < n-1; i++)
    {
        ExpandCenter(src, tmp_dest, i, i);
        if (strlen(tmp_dest) > maxLen)
        {
            maxLen = strlen(tmp_dest);
            subString(tmp_dest, dest, 0, maxLen);
        }
        ExpandCenter(src, tmp_dest, i, i+1);
        if (strlen(tmp_dest) > maxLen)
        {
            maxLen = strlen(tmp_dest);
            subString(tmp_dest, dest, 0, maxLen);
        }
    }
}

int main ( int argc, char *argv[] )
{
    char str[] = "3321123";
    cout << "Str is : " << str << endl;
    char* dest = new char[strlen(str)+1];
    char *tmp = LongestPalindromeDP(str);
    cout << "In dp solution is :" << tmp << endl;
    delete tmp;
    LongestPalindromeSimple(str, dest);
    cout << "In simple solution is :" << dest << endl;
    delete dest;
	return 0;
}		// ----------  end of function main  ---------- 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值