最长回文子串——Manacher算法

#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
char c[2000010];
void Insert(string s){
    c[0]='@';
    for(int j=0; j<s.length(); j++){
        c[2*(j+1)]= '@';
        c[2*j+1]=s[j];
    }
}

int min(int a, int b){
    return a>b?b:a;
}

int main()
{
    int n;
    int mx;
    int p;
    int max;
    string s;
    vector<int> v;
    cin>>n;
    for(int j=0; j<n; j++){
        cin>>s;
        Insert(s);
        max=0;
        mx=0;
        p=0;
        v.clear();
        int l=2*s.length()+1;
        for(int i=0; i<l; i++){
            //cout<<max<<endl;
            if(mx>i){
                v.push_back(min(mx-i, v[p*2-i]));
            }else{
                v.push_back(1);
            }
            while(c[i+v[i]]==c[i-v[i]] && (i+v[i])<l && (i-v[i])>=0) v[i]++;
            if((v[i]+i)>mx) {
                mx=v[i]+i;
                p=i;
            }
            if(v[i]>max) max=v[i];
        }
        cout<<max-1<<endl;
    }
    return 0;
}

hihoCoder的1032道题的解题代码


附上最易理解的

算法讲解讲解

http://m.blog.csdn.net/article/details?id=42061017


以及我理解的Manacher算法:

该算法的思想是从中心向两边探索回文,并标记之前探索的回文右边最远的字符的下标

1)如果是这种情况:

0  1  2  3  4  5  6  7  8  9  10

c  b  c  d   c  b  c   c  e  c    a

比如现在我要探索的是b(下标5),之前探索的以d(下标3)文中心的最长回文是c  b  c  d  c  b  c,右边最远字符是c(下标6),以d为中心最有两边是对称的,b(下标5)的对称点是b(下标1),右边最远字符c(下标6)关于d的对称点是下标0的字符c,则b(下标1)到c(下标0)这部分的对应字符是b(下标5)到c(下标0),这部分字符前面已经探索过了,可以跳过匹配过的,从c(下标7)开始探索,因为这部分是未探索过的。


2)如果是这种情况:

0  1  2  3  4  5  6  7  8  9  10

a  b  c  d  c  b  a   c   e   c    a

比如现在我要探索的是c(下标7),之前探索的以d(下标3)文中心的最长回文是c  b  c  d  c  b  c,右边最远字符是c(下标6),c(下标7)是一个新的字符,自己本身都没有匹配过,因此只能老老实实的一个一个的两边匹配了。



以上是我的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值