# COI2016 Palinilap（manacher+后缀数组）

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL long long
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const double alp = 0.75;
const LL INF = 1ll<<61;
const int MAXN = 200005;

int N;
char s[MAXN];
int olen[MAXN], elen[MAXN];
void manacher()
{
static char tmp[MAXN*2];
static int p[MAXN];
int M = N*2 + 1;
for (int i = 0; i<M; ++i) tmp[i] = '#';
for (int i = 0; i<N; ++i) tmp[i*2+1] = s[i+1];
for (int i = 0, j = 0, k; i<M; )
{
while (i-j>=0 && i+j<M && tmp[i-j]==tmp[i+j]) ++j;
p[i] = j;
for (k = 1; p[i-k] < p[i]-k; ++k) p[i+k] = p[i-k];
i += k, j = max(0, j-k);
}
rep(i, 1, N) olen[i] = p[(i-1)*2+1]>>1;
rep(i, 1, N) elen[i-1] = p[(i-1)*2]>>1;
}

int sa[MAXN], rnk[MAXN], height[MAXN], f[20][MAXN], lg2[MAXN];
#define lch(a) tr[a].ch[0]
#define rch(a) tr[a].ch[1]
int ncnt, rt, len, gt, gtf, tmr;
LL lpos, rpos;
struct Node {
int ch[2], c, sa, sz;
LL key;
} tr[MAXN];
int pt[MAXN], pn;
inline int cmp(int x, int y)
{
if (tr[x].c^tr[y].c) return tr[x].c < tr[y].c;
return tr[x-1].key < tr[y-1].key;
}
inline void pushup(int x)
{
tr[x].sz = tr[lch(x)].sz + tr[rch(x)].sz + 1;
}
{
return max(tr[lch(x)].sz, tr[rch(x)].sz) > tr[x].sz*alp;
}
void treavel(int x)
{
if (!x) return;
treavel(lch(x)), pt[++pn] = x, treavel(rch(x));
}
int build(int L, int R, LL l, LL r)
{
if (L>R) return 0;
int md = (L+R)>>1;
int x = pt[md];
tr[x].key = l+r;
LL mid = (l+r)>>1;
lch(x) = build(L, md-1, l, mid);
rch(x) = build(md+1, R, mid, r);
return pushup(x), x;
}
void ins(int&x, LL l, LL r)
{
if (!x) { x = ncnt; tr[x].key = l+r; return; }
LL mid = (l+r)>>1;
int d = cmp(x, ncnt);
if (!d) ins(lch(x), l, mid);
else ins(rch(x), mid, r);
if (pushup(x), isbad(x)) gt = x, gtf = 0, lpos = l, rpos = r;
else if (gt==lch(x)||gt==rch(x)) gtf = x;
}
void extend(int c, int p)
{
++ncnt, tr[ncnt].sa = p, tr[ncnt].c = c;
gt = pn = 0, ins(rt, 1, INF);
if (!gt) return;
treavel(gt);
if (!gtf) rt = build(1, pn, 1, INF);
else if (gt==lch(gtf)) lch(gtf) = build(1, pn, lpos, rpos);
else rch(gtf) = build(1, pn, lpos, rpos);
}
void dfs(int u)
{
if (!u) return;
dfs(lch(u)), sa[++tmr] = tr[u].sa, dfs(rch(u));
}
void MakeST()
{
rep(i, 1, N) f[0][i] = height[i];
rep(j, 1, 18) rep(i, 1, N-(1<<j)+1) f[j][i] = min(f[j-1][i], f[j-1][i+(1<<(j-1))]);
}
inline int quary(int l, int r)
{
int t = lg2[r - l + 1];
return min(f[t][l], f[t][r - (1<<t) + 1]);
}
inline int lcp(int a, int b)
{
if (a == b) return N*2 - a + 1;
a = rnk[a], b = rnk[b];
if (a > b) swap(a, b);
return quary(a+1, b);
}
void makesa()
{
rep(i, 1, N) extend(s[i], 2*N-i+1);
erp(i, N, 1) extend(s[i], i);
dfs(rt);
rep(i, 1, N) s[i+N] = s[N-i+1];
N*=2;
rep(i, 1, N) rnk[sa[i]] = i;
rep(i, 2, N) lg2[i] = lg2[i>>1]+1;
for (int i = 1, j = 0; i<=N; ++i, j&&--j)
{
if (rnk[i]==1) continue;
while (i+j<=N && sa[rnk[i]-1]+j<=N && s[i+j]==s[sa[rnk[i]-1]+j]) ++j;
height[rnk[i]] = j;
}
MakeST();
N/=2;
}

LL dv[MAXN], av[26][MAXN];
{
as[r+1] -= r-l+1;
}
{
l = N-l+1, r = N-r+1, swap(l, r);
asr[r+1] -= r-l+1;
}
void calsum()
{
rep(i, 1, N)
{
as[i] += as[i-1], asr[i] += asr[i-1];
}
reverse(asr+1, asr+N+1);
}

int getvalue(int l, int r)
{
if (l<1||r>N) return 0;
int res = lcp(r, 2*N-l+1);
res = min(res, min(l, N-r+1));
return res;
}

void calcLoss()
{
for (int i = 1, l, r; i<=N; ++i)
{
if (olen[i]!=1)
{
l=i-olen[i]+1, r=i+olen[i]-1;
}
if (elen[i]!=0)
{
l=i-elen[i]+1, r=i+elen[i];
}
}
}

void calcValue()
{
for (int i = 1, l, r, len; i<=N; ++i)
{
l = i-olen[i]+1, r = i+olen[i]-1;
if (l!=1 && r!=N)
{
l --, r ++;
len = getvalue(l-1, r+1);
av[s[r]-'a'][l] += len+1;
av[s[l]-'a'][r] += len+1;
}
l = i-elen[i]+1, r = i+elen[i];
if (l!=1 && r!=N)
{
l --, r ++;
len = getvalue(l-1, r+1);
av[s[r]-'a'][l] += len+1;
av[s[l]-'a'][r] += len+1;
}
}
}

int main()
{
scanf("%s", s+1);
N = strlen(s+1);
manacher();
makesa();
calcLoss();
calsum();
calcValue();
LL sum = 0;
rep(i, 1, N) sum += elen[i]+olen[i];
LL ans = sum;
rep(i, 1, N) rep(j, 0, 25)
ans = max(ans, sum - dv[i] + av[j][i]);
cout << ans << '\n';
return 0;
}


• 本文已收录于以下专栏：

## Hdu 5785 Interesting（Manacher+区间处理）

• wang2147483647
• 2017年09月06日 22:32
• 346

## 五分钟搞懂后缀数组！后缀数组解析以及应用(附详解代码)

• YxuanwKeith
• 2016年02月05日 13:13
• 17630

## 后缀数组：原理和实现

• ruoruo_cheng
• 2016年08月21日 21:47
• 1825

## 后缀数组罗穗蹇模板（dc3）

#include #include #include #include #define maxn 1000003 #define F(x) ((x)/3+((x)%3==1?0:tb)) #defin...
• u013665921
• 2014年10月14日 09:52
• 1396

## 后缀数组倍增法

• reverie_mjp
• 2016年04月17日 22:04
• 496

## 后缀数组详解

• qq_34731703
• 2016年10月26日 14:50
• 3566

## 实用算法实现-第8篇 后缀树和后缀数组 [1简介]

8.1    后缀树 一棵后缀树包含一个指定文本的所有后缀，对于在一个长度为N的文本中查找一个长度为M的子字符串，一个后缀树仅仅需要M次比较，而这个比较次数是查找该字符串所需要的最小比较次数。 后...
• fsdev
• 2011年10月15日 11:50
• 3816

## HDU 1403 Longest Common Substring(后缀数组入门)

• xtttgo
• 2016年08月14日 10:28
• 263

## 后缀数组练习题若干

POJ 1743    不可重叠最长重复子串 二分答案。 即子串的长度，假设为k时。 利用height数组，将排序后的后缀分为若干组。 每组内的height值都不小于k。 然后只需查看组内是否有满足要...
• sdj222555
• 2013年10月13日 21:00
• 2485

## 后缀数组——罗穗骞倍增算法代码详解

• rockzh1993
• 2015年12月19日 10:28
• 1913

举报原因： 您举报文章：COI2016 Palinilap（manacher+后缀数组） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)