Template of MANACHER for Solving Palindromes Substring

The algorithm of Manacher is a method for searching all the substrings which are in the form of palindrome in O(n) time.

//programed under gcc environment
#include<stdio.h>
#include<string.h>

int min(int _x,int _y){
    //to choose a smaller integer
    return _x < _y ? _x : _y;
}

//data definations
//maxl: the longest length for str
#define maxl (1000000+1)

//r:radius in the processed string
//  -> the offset from middle to the end in a palindrome
int r[maxl*2];
//r is also the real length in the formar string

//str:the string for input
//chr:str with separator
char str[maxl],chr[maxl*2];

void manacher(){
    //translate str into '#'
    int len=strlen(str),i;
    //i<=len means including the end flag '\0'
    for(i=0;i<=len;i++){
        chr[ 2*i   ]='#';
        chr[ 2*i+1 ]=str[i];
    }
    //mxl: right set of availeble segment
    //pos: the middle for the furthest palindrome 
    int pos=0,mxl=0;
    r[0]=0;
    //for each offset in chr,solve once
    for(i=0;i< 2*len+1 ;i++){
        if(mxl>i){//check if in available segment 
            r[i]=min(mxl-i,r[2*pos-i]);
        }else r[i]=0;//not in
        while(//check if "r" can be larger
            i+r[i]+1 < 2*len+1 && i-r[i]-1>=0 &&
            chr[i+r[i]+1] == chr[i-r[i]-1]
            //!attention: "i+r[i]+1 < 2*len+1" not "<len"
        )r[i]++;//push forward once
        if(i+r[i]>mxl){//check and change available area
            mxl=i+r[i];//new right set
            pos=i;//new middle for palindrome
        }
    }
}

void outp(){
    int i;
    for(i=0;chr[i];i++){
        //output message "chr" and "r"
        printf("%c:%5d\n",chr[i],r[i]);
    }
}

int main(){
    //for test only
    while(1){
        //input string
        scanf("%s",str);
        //run the algorithm "manacher"
        manacher();
        //output message of MANACHER
        outp();
    }
    return 0;
}

There are two main ideas in this algorithm:

Set Separator

For the symmetric center of a palindrome can be set in the middle of two characters (but not on a letter), such as “abba” ‘s sym-cen is between the two “b”s, we have to make two different algorithm if we want to solve both kinds of palindromes. Why not put something between each pair of adjacent chars, such as pocessing “abba” into “#a#b#b#a#”. This allow us to use only one algorithm to solve the whole problem.

Keep Track of the Furthest Reached Place.

For each position in the pocessed string, we use ri to record the radius of a position, that is the offset of the right set of the longest string, whose middle position is located in chri , from the middle of this substring. (Obviously, the so-called radium in the processed string is also the length of the palindrome in the unprocessed string.)

When we have got the values of r1..i1 , how can we get the value of ri . We can record two value called “pos” and “mxl”. mxl is the furthest position you have been to, pos is the middle position of the substring (of cause, palindromic) by which you arrived mxl. If i lies between pos and mxl, ri can’t be less than min{mxli,r2posi} . Position 2posi is the symmetric position of position i , mxli is the distance between the position i and the furthest position. But if not, we can only know that ri0 . After we got the minimum value, try to push ri forward as far as you can. After solve ri , change variable pos and mxl into new values if needed.

mxl can only become larger, and we make full use of the message we’ve got, this algorithm can be done in O(n) time .

Finally

Please forgive me for my grammatical and spelling mistakes.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值