# 【SAM manacher 倍增】bzoj3676: [Apio2014]回文串

【数据规模与评分】

## 题目分析

 1 #include<bits/stdc++.h>
2 const int maxn = 600035;
3
4 int n,g[maxn],lg2[maxn>>1];
5 long long ans;
6 int size[maxn],dep[maxn],id[maxn],sta[maxn];
7 int cnt[maxn],pos[maxn];
8 char s[maxn],t[maxn];
9 struct SAM
10 {
11     int lst,tot;
12     int fa[maxn][21],len[maxn];
13     std::map<int, int> ch[maxn];　　　　　　　　　　//似乎略卡空间
14     SAM(){lst = tot = 1;}
15     void extend(int c, int id)
16     {
17         int p = lst, np = ++tot;
18         lst = np, len[np] = len[p]+1, sta[id] = np;                    //sta[np]=id
19         for (; p&&!ch[p][c]; p=fa[p][0]) ch[p][c] = np;
20         if (!p) fa[np][0] = 1;
21         else{
22             int q = ch[p][c];
23             if (len[q]==len[p]+1) fa[np][0] = q;
24             else{
25                 int nq = ++tot;
26                 len[nq] = len[p]+1, ch[nq] = ch[q];
27                 fa[nq][0] = fa[q][0], fa[q][0] = fa[np][0] = nq;
28                 for (; ch[p][c]==q; p=fa[p][0]) ch[p][c] = nq;
29             }
30         }
31         size[np] = 1;
32     }
33     void build()
34     {
35         for (int i=1; i<=tot; i++) ++cnt[len[i]];
36         for (int i=1; i<=tot; i++) cnt[i] += cnt[i-1];
37         for (int i=tot; i>=1; i--) pos[cnt[len[i]]--] = i;
38         for (int i=tot; i>=1; i--)
39             size[fa[pos[i]][0]] += size[pos[i]];
40         for (int i=1; i<=tot; i++)
41         {
42             int p = pos[i];
43             dep[p] = dep[fa[p][0]]+1;
44             for (int j=1; j<=20; j++)
45                 fa[i][j] = fa[fa[i][j-1]][j-1];
46         }
47     }
48     void match(int l, int r)
49     {
50         if (l > r||l < 1||r > n) return;
51         int p = sta[r];
52         for (int i=lg2[dep[p]]; i>=0; i--)
53         {
54             int fat = fa[p][i];
55             if (len[fat] >= r-l+1) p = fat;
56         }
57         ans = std::max(ans, 1ll*size[p]*(r-l+1));
58     }
59 }f;
60
61 void manacher()
62 {
63     int m = 0, mid = 1;
64     t[0] = '!', t[++m] = '@';
65     for (int i=1; i<=n; i++)
66         t[++m] = s[i], id[m] = i, t[++m] = '@';
67     for (int i=1, mx=-1; i<m; i++)
68     {
69         if (i >= mx) g[i] = 1;
70         else g[i] = std::min(mx-i, g[2*mid-i]);
71         f.match(id[i-g[i]+2], id[i+g[i]-2]);
72         for (; t[i-g[i]]==t[i+g[i]]; )
73             ++g[i], f.match(id[i-g[i]+2], id[i+g[i]-2]);        //id[i-g[i]], id[i+g[i]]
74         if (i+g[i] > mx) mx = i+g[i], mid = i;
75     }
76 }
77 int main()
78 {
79     scanf("%s",s+1);
80     n = strlen(s+1);
81     for (int i=1; i<=n; i++)
82         f.extend(s[i]-'a', i), lg2[i] = i>1?(lg2[i>>1]+1):0;
83     f.build();
84     manacher();
85     printf("%lld\n",ans);
86     return 0;
87 }

END

posted @ 2019-03-13 20:35  AntiQuality  阅读(101)  评论(0编辑  收藏  举报