manecher算法 最长回文子字符串

还没放假的时候就知道有这么一种算法,之前看了一下以为很难就没好好学,今天早上用心看了一下,发现其实很简单。学什么东西都应该静下心来好好理解好好学,才能保证高效率!


我主要是看这篇博客学的马拉车,我觉得讲的已经够好了,仔细看一遍,应该问题不大。


马拉车其实非常巧妙,确实难以想到这种解决方法,但是学算法不是让你发明,单纯的学习其实还是很简单的。具体的思路可以看上面的链接博客,这里只讲一下核心优化内容。


a b c b e b c b a g

1 2 3 4 5 6 7 8 9 10


上面给出了一个字符串abcdedcba,我们可以发现以e为中心、5为半径的字符是回文字符串,那么我们要求序号为7的最长回文串时,因为回文串的对称原理,并且字符3和字符7在同一回文串的对称位置。它的长度最少是序号为3的最长回文串的长度。

贴上代码:

int R[MAX * 2];
char a[MAX];
char b[MAX * 2];
int main()
{
    cin >> a;
    b[0] = '@',
    b[1] = '#';
    int len = strlen(a);
    int ct = 2;
    for (int i = 0; i < len; i++)
    {
        b[ct++] = a[i];
        b[ct++] = '#';
    }
    b[ct] = '$';
    int pos = 0, mx = 0, ans = 0; 
    //pos代表上一次最远半径的中心,mx代表最远半径的位置+1,
    for (int i = 1; i < ct; i++)
    {
        if (i < mx)
            R[i] = min(mx - i, R[2 * pos - i]); //manecher算法核心
        else
            R[i] = 1;
        while (b[i + R[i]] == b[i - R[i]])
            R[i]++;
        if (R[i] + i > mx)
            pos = i, mx = R[i] + i;
        ans = max(ans, R[i] - 1);
    }
    cout << ans << endl;
    return 0;
}
发布了91 篇原创文章 · 获赞 67 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hesorchen/article/details/105116749