HDU3068 最长回文(manacher模板

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

Input输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000Output每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input

aaaa

abab

Sample Output

4
3
 1 #define maxn 1000010
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cstring>
 6 
 7 using namespace std;
 8 
 9 char str[maxn] ;//原字符串
10 char tmp[maxn << 1];//转换后的字符串
11 int Len[maxn << 1];
12 
13 //转换原始串
14 int INIT(char *st)
15 {
16     int i, len = strlen(st);
17     tmp[0] = '@';//字符串开头增加一个特殊字符,防止越界
18     for (i = 1; i <= 2 * len; i += 2)
19     {
20         tmp[i] = '#';
21         tmp[i + 1] = st[i / 2];
22     }
23     tmp[2 * len + 1] = '#';
24     tmp[2 * len + 2] = '$';//字符串结尾加一个字符,防止越界
25     tmp[2 * len + 3] = 0;
26     return 2 * len + 1;//返回转换字符串的长度
27 }
28 //Manacher算法计算过程
29 int MANACHER(char *st, int len)
30 {
31     int mx = 0, ans = 0, po = 0;//mx即为当前计算回文串最右边字符的最大值
32     for (int i = 1; i <= len; i++)
33     {
34         if (mx > i)
35             Len[i] = min(mx - i, Len[2 * po - i]);//在Len[j]和mx-i中取个小
36         else
37             Len[i] = 1;//如果i>=mx,要从头开始匹配
38         while (st[i - Len[i]] == st[i + Len[i]])
39             Len[i]++;
40         if (Len[i] + i > mx)//若新计算的回文串右端点位置大于mx,要更新po和mx的值
41         {
42             mx = Len[i] + i;
43             po = i;
44         }
45         ans = max(ans, Len[i]);
46     }
47     return ans - 1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度 
48 }
49 
50 
51 int main()
52 {
53     while(cin>>str){
54         int len = INIT(str);
55         cout<<MANACHER(tmp, len)<<endl;
56         
57     }
58 }

 

posted @ 2019-10-22 14:08  小草今天又在摸鱼吗  阅读(115)  评论(0编辑  收藏  举报