把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

模板:manacher算法

https://www.luogu.org/problemnew/show/P3805

回文串长度的奇偶性造成了对称轴的位置可能在某字符上,也可能在两个字符之间的空隙处

那么manacher对此的优化是在每两个字符中间插入另一个字符,如'#'。

用一个辅助数组r表示每个点能够扩展出的回文长度

我们先设置一个辅助变量maxright,表示已经触及到的最右边的字符

另外还要设置一个辅助变量mid,表示包含maxright的回文串的对称轴所在的位置

当i在maxright左边且在mid右边时:

设i关于mid的对称点为j,显然r[i]一定不会小于r[j]。(对称)

我们没必要保存j,j可以通过计算得出,为:(mid<<1)−i

那么我们就设置r[i]=r[j]然后继续尝试扩展,这样就可以较快地求出r[i],然后更新maxright和mid

当i在maxright右边时,我们无法得知关于r[i]的信息,只好从1开始遍历,然后更新maxright和mid

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 char t[11000010], a[11000010];
 6 int n, m, ans=0;
 7 int r[23000000];
 8 int main() {
 9     scanf("%s", t);
10     m=strlen(t);
11     a[0]=a[1]='#';
12     for(int i=1; i<=m; i++){
13         a[(i<<1)]=t[i-1];
14         a[(i<<1)+1]='#';
15     }
16     n=(m<<1)+2;
17     int mid=1, maxright=1;
18     r[1]=1;
19     for(int i=2; i<n; i++){
20         if(i<maxright) r[i]=min(r[(mid<<1)-i], r[mid]+mid-i); 
21         else  r[i]=1;
22         while(a[i-r[i]]==a[i+r[i]]) r[i]++;
23         if(i+r[i]>maxright){
24             maxright=i+r[i];
25             mid=i;
26         }
27         if(r[i]>ans)    ans=r[i];
28     }
29     printf("%d\n", ans-1);
30     return 0;
31 }

 

posted @ 2018-11-01 18:52  AZe-qwq  阅读(159)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end