# COI2016 Palinilap（manacher+后缀数组）

218人阅读 评论(0)

#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;
}


0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：48248次
• 积分：1466
• 等级：
• 排名：千里之外
• 原创：98篇
• 转载：0篇
• 译文：0篇
• 评论：4条
友情链接
阅读排行
最新评论