Leetcode Q5:Longest Palindromic Substring

题目5:

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

/***************************************************************************************************
*                    (c) Copyright 1992-2015 Embedded Products Research Center
*                                       All Rights Reserved
*
*\File          main.c
*\Description   使用Manacher算法找出字符串S中唯一最长回文子串,时间复杂度为O(N)
*\Note          
*\Log           2015.07.27    Ver 1.0    
*               创建文件。
***************************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/***************************************************************************************************
*\Function      GetLen
*\Description   获取时间字符串长度
*\Parameter     s
*\Return        int
*\Note          
*\Log           2015.07.27    Ver 1.0    
*               创建函数。
***************************************************************************************************/
int GetLen(char* s)
{
    int len = 0;
    while (*(s++) != '\0')
    {
        len++;
    }
    return len;
}

/***************************************************************************************************
*\Function      StringExten
*\Description   扩充字符串到extern_s,例"abc"扩充为"#a#b#c#"
*\Parameter     s
*\Parameter     extern_s
*\Return        int
*\Note          
*\Log           2015.07.27    Ver 1.0    凌琨
*               创建函数。
***************************************************************************************************/
void StringExten(char* s, char* extern_s)
{
    int len = 0;
    int i = 0;
    len = GetLen(s);
    for (i = 0; i < len; i++)
    {
        extern_s[2*i] = '#';
        extern_s[2*i+1] = s[i];
    }
    extern_s[2*i] = '#';
    extern_s[2*i+1] = '\0';
}


/***************************************************************************************************
*\Function      StringCut
*\Description   去除扩充字符
*\Parameter     s
*\Parameter     res
*\Return        void
*\Note          
*\Log           2015.07.27    Ver 1.0    
*               创建函数。
***************************************************************************************************/
void StringCut(char* s, char* res)
{
    int len = 0;
    int i = 0;
    len = GetLen(s);
    for (i = 0; i < (len-1)/2; i++)
    {
        res[i] = s[2*i+1];
    }
    res[i] = '\0';
}

char* longestPalindrome(char* s) 
{
    int i = 0;
    int temp_l = 0;
    int temp_r = 0;
    int s_len = 0;
    int extern_len = 0;
    char* extern_s = NULL;                           /* 扩充后字符串 */
    char* res = NULL;                                /* 存放最终结果 */
    int* arr_r = NULL;                               /* 记录每个位置为中心的回文半径 */
    int max_ptr = 0;                                 /* 最长回文可到的标号 */
    int max_center = 0;                              /* 最长回文的中心 */
    s_len = GetLen(s);
                                  
    extern_s = (char*)malloc(2*s_len+2);
    res = (char*)malloc(s_len+1);                    /* 存放返回结果 */
    arr_r = (int*)malloc(sizeof(int)*(2*s_len+2));   /* 每个节点的回文半径长度 */

    StringExten(s, extern_s);
    extern_len = GetLen(extern_s);

    /* 遍历求得所有的arr_r[i] */
    for (i = 0; i < extern_len; i++)
    {
        arr_r[i] = 0;
        /* 节点不被之前最大回文所包括在内,按普通方法求该点的回文半径 */
        if (i >= max_ptr)
        {
            temp_l = i;
            temp_r = i;
            arr_r[i] = 1;
            while (--temp_l >= 0 && ++temp_r <= extern_len)
            {
                if (extern_s[temp_l] == extern_s[temp_r])
                {
                    arr_r[i] += 1;
                }
                else
                {
                    break;
                }
            }
        }
        else    /* 被之前求得的最大回文半径所包括在内,分了三种情况 */
        {
            if ((2*max_center-i - arr_r[2*max_center-i] + 1) < 2*max_center-max_ptr)
            {
                arr_r[i] = arr_r[2*max_center - i];
            }
            if ((2*max_center-i - arr_r[2*max_center-i] + 1) > 2*max_center-max_ptr)
            {
                arr_r[i] = arr_r[max_center] - (i - max_center);
            }
            if ((2*max_center-i - arr_r[2*max_center-i] + 1) == 2*max_center-max_ptr)
            {
                arr_r[i] = arr_r[2*max_center - i];
                temp_l = i - (max_ptr - i);
                temp_r = max_ptr;
                while (--temp_l >= 0 && ++temp_r <= extern_len)
                {
                    if (extern_s[temp_l] == extern_s[temp_r])
                    {
                        arr_r[i]++;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            
        }
        /* 判断是否修改标记 */
        if (arr_r[i] > arr_r[max_center])
        {
            max_center = i;
            max_ptr = max_center + arr_r[i] - 1;
        }
    }
    extern_s[max_ptr+1] = '\0';
    StringCut(&extern_s[max_center+1-arr_r[max_center]], res);
    free(extern_s);
    free(arr_r);
    return res;
}

void main()
{
    static char str[] = "ccc";
    char* res = (char*)malloc(10000);
    res = longestPalindrome(str);
    printf("%s\n", res);
    getchar();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值