hdu 3068 最长回文

传说中的马拉车算法233

(先吐槽,manacher我一直觉得打成manachar比较对2333)

manachar的第一步(很神奇的一步),就是把原串每个字符中间再加上一个原串没有出现的字符,为什么这样搞呢?

自己可以画一个图看一下:2333其实加上直接,原来的回文长度就都是奇数了。

然后有2个变量,mx和id,表示id位置的回文长度最大,到了mx位。还有一个p[]数组,表示每个位置的回文长度。最后的答案就是max{p[i]}-1(不要问为什么)

那么这些东西是怎么work(用高大上的词汇)的呢?

http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html

大概的意思就是利用了回文的性质,用 i 关于 id 的对称点 j 来更新 i 的答案,当然是在 i<mx 的前提下。那么用对称点跟新过来的答案就是min(p[j],mx-i)

然后剩下不知道的再暴力匹配就好。

因为这个东西的mx就正好跑完一个串,所以复杂度肯定是O(n)的啊233

裸题:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <iostream>
 6 #define LL long long
 7 using namespace std;
 8 
 9 const int maxn=233333;
10 
11 int len[maxn<<1];
12 char a[maxn];
13 
14 int manachar(char *p)
15 {
16     char s[maxn<<1];
17     int n=strlen(p),l=0;
18     s[l++]='@'; s[l++]='#';
19     for (int i=0; i<n; i++)
20     {
21         s[l++]=p[i];
22         s[l++]='#';
23     }
24     s[l++]='~'; s[l]=0;
25     int mx=0,pos=0,ans=0;
26     for (int i=1; i<l; i++)
27     {
28         if (mx>i) len[i]=min(len[2*pos-i],mx-i); else len[i]=1;
29         while (s[i+len[i]]==s[i-len[i]]) len[i]++;
30         ans=max(ans,len[i]);
31         if (len[i]+i>mx) mx=len[i]+i,pos=i;
32     }
33     return ans-1;
34 }
35 
36 int main()
37 {
38     while (scanf("%s",a)!=EOF) printf("%d\n",manachar(a));    
39 }

 

posted @ 2017-04-19 10:27  ws_ccd  阅读(129)  评论(0编辑  收藏  举报