最长回文子字符串

来源:互联网 发布:python 定时发送邮件 编辑:程序博客网 时间:2024/05/22 04:34

给出一个字符串,我们需要找到最长的回文子字符串,回文子字符串有两种,一种是奇数型,如aba,一种是偶数形,如abba,所谓的回文字符串就是这个字符串正读或者倒度都是相同的。为了统一处理这两种回文字符串,我们将原字符串每隔一个字符,添加一新字符,我们在这里用来表示,举个例子就是将aba变成aba,这样任何的回文字符串都是奇数长。
我们将对变换过后的字符串进行扫描。记录以每个元素为中心的最长回文字符串的半径长度。同时我们记录这个回文字符串最右端的位置和maxid进行比较,如果比它大就将它更新,我们用下图来说明这样做的目的

这里写图片描述
假设当前扫描到第i个位置,以它为中心的最长回文字符串的最右端位置为maxid,那么如果下一个扫描到的是位置j,它关于i的对称位置为2ij,显然两者的回文长度在maxid内是相等的,所以我们便可以确定以j为中心的会问长度半径长度为min{P[2ij],maxidj},其中P[2ij]表示的就是以2ij位置上的元素为中心的最长回文字符串的半径长度。
这样我们就得到了变换后的字符串的每个元素为中心的最长回文字符串的半径长度。当然包括,接下来的事情就是读出最长的回文字符串,因为我们在上步中已经记录了最长回文字符串所对应的位置,这样,我们找到这个位置,设为i,那么在原字符中的最长回文串的最左端的字符为为变换过后的字符串的第ip+2位置上的字符,最右端的字符为变换过后的字符串的第i+p2的元素。

char *longestPalindrome(char *s){    int len_s=strlen(s);    char *new_s=malloc(sizeof(char)*(2*len_s+3));    int *P=malloc(sizeof(int)*(2*len_s+3));    char *result=malloc(sizeof(char)*(len_s+1));    new_s[0]='#';    new_s[2*len_s+2]='$';    int i;    int max_len=0;    int maxid=0;    int id=0,len_id=0;    for(i=1;i<=2*len_s+2;i++)    {        if(i % 2==1)            new_s[i]='*';        else            new_s[i]=s[(i-2)/2];    }    for(i=1;i<2*len_s+2;i++)    {        if(i<maxid)            P[i]=P[2*id-i]>(maxid-i)?(maxid-i):P[2*id-i];        else            P[i]=1;        while(new_s[i-P[i]]==new_s[i+P[i]])            P[i]++;        if(i+P[i]>maxid)        {            maxid=i+P[i];            id=i;        }        if(P[i]>max_len)        {            max_len=P[i];            len_id=i;        }    }    memcpy(result,s+(len_id-max_len)/2,max_len-1);    result[max_len-1]='\0';    return result;}
0 0