hdu 3068 最长回文(manacher)

Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等  

 

Input 输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000  

 

Output 每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.  

 

Sample Input aaaa abab   Sample Output 4 3

 思路:马拉车模板体

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long int
using namespace std;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
int p[1000007]; //记录半径 
void manacher(string s){
    string ma="";
    ma+='$';
    ma+='#';
    int len=s.length();
    //预处理字符串 加#是为了让长度变为奇数(避免讨论奇偶)
    //二加$则是为了求字符串的起始位置 在博客中有相关叙述 
    for(int i=0;i<len;i++){
        ma+=s[i];
        ma+='#';
    }
    int po=0; int mx=0; //po记录当前可以延伸到最右端的点 mx为长度 
    len=ma.length();
    for(int i=0;i<len;i++){
        p[i]=mx>i?min(p[2*po-i],mx-i):1; //关键代码 在博客中理解 
        while(ma[i+p[i]]==ma[i-p[i]]) p[i]++;
        if(i+p[i]>mx){ //更新 
            mx=i+p[i];
            po=i;
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    string s;
    while(cin>>s){
        manacher(s);
        int len=s.length();
        int ans=0;
        for(int i=0;i<2*len+2;i++)
            ans=max(ans,p[i]-1); //找最长的长度 
        cout<<ans<<endl;
    }
    return 0;
}
上一篇:ADUM1400CRWZ-RL四通道数字隔离器ADI 4/0通道定向性


下一篇:后缀数组板子