P3805 【模板】manacher演算法
阿新 • • 發佈:2021-02-16
文章目錄
R e s u l t Result Result
H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.com.cn/problem/P3805
D e s c r i p t i o n Description Description
給定一個長度為 n n n的字串,求其最長迴文子串
資料範圍: n ≤ 1.1 × 1 0 7 n\leq 1.1\times 10^7 n≤1.1×107
S o l u t i o n Solution Solution
在串的最前面新增一個字元
∼
\sim
∼
在末尾新增一個換行符
中間新增一手
∣
|
∣
將串
A
B
C
C
B
A
ABCCBA
ABCCBA轉化成
∼
∣
A
∣
B
∣
C
∣
C
∣
B
∣
A
∣
\sim|A|B|C|C|B|A|
∼∣ A∣B∣C∣C∣B∣A∣
接著設 m i d mid mid表示當前處理出最大回文串的中心, m x mx mx表示此串最遠的拓展中心, p i p_i pi表示以 i i i為迴文中心的最長半徑
每次只需令 p i = m i n { m x − i , p 2 m i d − i } p_i=min\{mx-i,p_{2mid-i}\} pi=min{mx−i,p2mid−i}然後暴力匹配即可
時間複雜度: O ( n ) O(n) O(n)
C o d e Code Code
#include<cstdio>
#include<cstring>
#include <algorithm>
#define LL long long
#define N 22000010
using namespace std;char s[N],news[N];
int n,newn,p[N];
inline void Init()
{
news[0]='~';news[1]='|';newn=2;
for(register int i=0;i<n;i++) news[newn++]=s[i],news[newn++]='|';
news[newn]=10;return;
}
inline int Manacher()
{
int mid=1,mx=1,ans=0;
for(register int i=1;i<newn;i++)
{
if(i<mx) p[i]=min(mx-i,p[2*mid-i]);else p[i]=1;
while(news[i-p[i]]==news[i+p[i]]) p[i]++;
if(mx<i+p[i])
{
mid=i;
mx=i+p[i];
}
ans=max(ans,p[i]-1);
}
return ans;
}
signed main()
{
scanf("%s",s);
n=strlen(s);Init();
printf("%d\n",Manacher());
}