回文串的Manacher算法

Manacher算法较传统算法的优化之处在于它对每个回文中心寻找回文半径的时候并不是都从半径为1开始找的,而是利用前面已经完成的任务,寻找一个初始的开始搜索的半径大小,复杂度是线性的。

参考博客:https://www.cnblogs.com/z360/p/6375514.html

下面附上hdoj的3068模板:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define dbg(args) cout<<#args<<":"<<args<<endl;
17 #define inf 0x3f3f3f3f
18 #define maxn 110005
19 int n,m,t;
20 char s[maxn];
21 char tmp[maxn<<1];
22 int l[maxn<<1];//转换后的字符串以及最大回文半径 
23 int manacher(char *st,int len) 
24 {
25     int t=0;
26     tmp[t++]='$';
27     tmp[t++]='#';
28     f(i,0,len-1)
29     {
30         tmp[t++]=s[i];
31         tmp[t++]='#';
32     }
33     tmp[t]=0;
34     int mr=0,ans=0,pos=0;//最长回文右端、最长回文长度以及回文中心 
35     f(i,0,t-1)
36     {
37         l[i]=mr>i?min(mr-i,l[2*pos-i]):1;
38         //i>=mr时需要以i为新的回文中心开始搜索回文长度  
39         while(tmp[i-l[i]]==tmp[i+l[i]])l[i]++;
40         if(i+l[i]>mr)//更新最大回文右端点 
41         {
42             mr=i+l[i];
43             pos=i;
44         }
45         ans=max(ans,l[i]);
46     }
47     return ans-1;//每次回文串长度为2*k+1时,多余字符为k+1个,有k个属于原串的字符 
48 }
49 int main()
50 {
51     //freopen("input.txt","r",stdin);
52     //freopen("output.txt","w",stdout);
53     std::ios::sync_with_stdio(false);
54     while(scanf("%s",s)!=EOF)
55     {
56         int len=strlen(s); 
57         pf("%d\n",manacher(tmp,len));
58     }
59     
60  } 

猜你喜欢

转载自www.cnblogs.com/randy-lo/p/12518125.html
今日推荐