Manacher算法(O(n)求得最长回文)

来源:互联网 发布:怎么玩网络赚钱 编辑:程序博客网 时间:2024/05/22 00:54

Manacher算法:

  非常快的求回文字符串的算法,它和普通回文字符串检索的区别就是,后者每个字符串的回文值(自定义为最长回文向左/右扩张长度)初始都是为1,而Manacher算法则可以利用前面已知的回文值,初始值不再仅仅是1,这就是其优化的地方。

  那么怎么利用前面已知的回文值得出有效信息呢?看这篇文章吧 数据结构与算法系列----Manacher算法【O(n)求得最长回文】,感觉讲的不错,看的其他文章都太复杂了,这个简洁明了,看了这个才懂了。



  在这注意到了自己一个不好的习惯,将strlen(str)放入for循环,会导致超时。

HDU-3068  最长回文

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 110005;char str[N],new_str[N*2];int p[N*2];int Manacher(){    int len = strlen(str);    new_str[0] = '$';    new_str[1] = '#';    int num = 2;    for (int i = 0; i < len; i++)    {        new_str[num++] = str[i];        new_str[num++] = '#';    }    new_str[num] = '\0';    int maxlen = 0;//最长回文长度    int id,mx = 0;    for (int i = 1; i < num; i++)    {        if (i < mx)            p[i] = min(p[2 * id - i], mx - i);        else            p[i] = 1;        while (new_str[i - p[i]] == new_str[i + p[i]])//不需边界判断,因为左有'$',右有'\0'            p[i]++;        if (mx < i + p[i])//更新        {            id = i;            mx = i + p[i];        }        maxlen = max(maxlen, p[i] - 1);    }    return maxlen;}int main(){    while (~scanf("%s", str))    {        printf("%d\n", Manacher());    }    return 0;}

POJ-3974

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 1000005;char str[N],new_str[N*2];int p[N*2];int Manacher(){    int len = strlen(str);    new_str[0] = '$';    new_str[1] = '#';    int num = 2;    for(int i = 0;i < len;i++)    {        new_str[num++] = str[i];        new_str[num++] = '#';    }    new_str[num] = '\0';    int maxlen = 0;    int id,mx = 0;    for(int i = 1;i < num;i++)    {        if(mx > i)            p[i] = min(p[id*2-i],mx - i);        else            p[i] = 1;        while(new_str[i + p[i]] == new_str[i - p[i]])            p[i]++;        if(mx < i + p[i])        {            id = i;            mx = i + p[i];        }        maxlen = max(maxlen,p[i]-1);    }    return maxlen;}int main(){    int ca = 1;    while(~scanf("%s",str))    {        if(strcmp(str,"END") == 0)            break;        printf("Case %d: %d\n",ca++,Manacher());    }    return 0;}


0 0
原创粉丝点击