hiho第一周——最长回文子串

来源:互联网 发布:互联主机销售系统源码 编辑:程序博客网 时间:2024/06/05 04:21

hiho第一周——最长回文子串

题目链接:http://hihocoder.com/contest/hiho1/problem/1
资料来源于网络:http://www.felix021.com/blog/read.php?2040

关键点

Manacher算法的关键点就在这里了:如果max_right> i,那么P[i] >= MIN(P[2 * ind - i], max_right- i)

上图方便理解:

当 mx - i > P[j] 的时候,以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于 i 和 j 对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以必有 P[i] = P[j],见下图。
这里写图片描述

当 P[j] >= mx - i 的时候,以S[j]为中心的回文子串不一定完全包含于以S[id]为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] >= mx - i。至于mx之后的部分是否对称,就只能老老实实去匹配了。
这里写图片描述

p.s.数组 P[i] 来记录以字符S[i]为中心的最长回文子串向左/右扩张的长度(包括S[i])

可执行代码

#include <iostream>#include <string>#include <fstream>#include <cmath>#include <vector>using namespace std;int longest_panlin(string s);int main(){    fstream cin("input.txt");    int N;    cin>>N;    while(N>0)    {        string s;        cin>>s;        int result;        result=longest_panlin(s);        cout<<result<<endl;        N--;    }    return 0;}int longest_panlin(string s){    //预处理,因为manacher算法对于奇数个字符的字符串,代码可以大大简化(但是这加大了空间复杂度)    string str="#";    for(int i=0;i<s.size();i++){str+=s[i];str+='#';}    //记录最长回文子串的长度。比如以c为中心的#a#c#a#,它的result为4,最终函数应该返回3    int result=0;    //右端最右的回文子串,它的中心位置    int ind=0;    //右端最右的回文子串,它的右端位置    int max_right=0;    int n=str.size();    //动态数组,记录以下标为中心位置,它的最长回文字串的右边长度(包括中心点)    int *p=new int[n];    p[0]=1;    for(int i=1;i<n;i++)    {        //该算法的核心思想,具体请看图        if(max_right>i)            p[i]=min(p[2*ind-i],max_right-i);        else            p[i]=1;        //在不越左边界,不越右边界的情况下,获取该中心的回文子串最大的长度        for(;i>=p[i]&&i+p[i]<n&&str[i+p[i]]==str[i-p[i]];)            p[i]++;        //记录结果        if(p[i]>result)result=p[i];        //不断获得右端最右的回文子串(这是为什么呢?是跟时间复杂度有关吗?)        if(p[i]+i>max_right)        {            max_right=p[i]+i;            ind=i;        }    }    delete p;    return result-1;}
0 0
原创粉丝点击