Nemlit 的博客

Nemlit 的博客

By a konjac

题解 P4555 【[国家集训队]最长双回文串】

posted on 2019-10-29 23:02:24 | under 题解 |

不知道有没有人跟我一样数据结构学傻了

首先这道题是要求回文串,那么我们可以想到manacher算法

但由于 $manacher$ 不能求出双回文子串,我们要考虑一些性质

首先对于一个回文串,删掉两边的字符它一样是回文串

然后 $manacher$ 求出的 $p$ 数组就是他能拓展的数量,发现对于一个点对 $i, j$ ,当满足 $i+p_i+1≥j-p_j+1$ 时,两个回文串有交集,根据上述性质,这对点对是可以构成双回文子串的

上述式子是可以用权值线段树实现的,每找到一个 $i+p_i$ ,丢尽权值线段树里面,每次查询权值线段树中 $[j-p_j, MAX]$ 的最小的 $i$ ,用 $j-i+1$ 更新答案即可

(注意本身就是一个回文串的情况)

$Code:$

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define rep(i, s, t) for(int i = s; i <= t; ++ i)
#define maxn 200005
#define inf 123456789
int n, m, cnt, p[maxn], Ans, MAX = 200000, mi[maxn << 2], pax;
char c[maxn], s[maxn];
#define ls k << 1
#define rs k << 1 | 1
il void build(int k, int l, int r) {
    mi[k] = inf;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
}
il void insert(int k, int l, int r, int ll, int v) {
    if(l == r) return(void)(mi[k] = min(v, mi[k]));
    int mid = (l + r) >> 1;
    if(ll <= mid) insert(ls, l, mid, ll, v);
    else insert(rs, mid + 1, r, ll, v);
    mi[k] = min(mi[ls], mi[rs]);
}
il int query(int k, int l, int r, int ll, int rr) {
    if(ll <= l && r <= rr) return mi[k];
    int mid = (l + r) >> 1, ans = inf;
    if(ll <= mid) ans = query(ls, l, mid, ll, rr);
    if(mid < rr) ans = min(ans, query(rs, mid + 1, r, ll, rr));
    return ans;
}
il void build() {
    scanf("%s", c + 1), n = strlen(c + 1), s[++ cnt] = '~', s[++ cnt] = '#';
    rep(i, 1, n) s[++ cnt] = c[i], s[++ cnt] = '#';
    s[++ cnt] = '!';
}
il void solve() {
    int mid = 0, mr = 0;
    rep(i, 2, cnt - 1) {
        if(i <= mr) p[i] = min(p[mid * 2 - i], mr - i + 1);
        else p[i] = 1;
        while(s[i - p[i]] == s[i + p[i]]) ++ p[i];
        if(i + p[i] > mr) mr = i + p[i] - 1, mid = i;
        Ans = max(Ans, i - query(1, 1, MAX, i - p[i] + 1, MAX));
        insert(1, 1, MAX, i + p[i], i), pax = max(pax, p[i]);
    }
    if(pax - 1 == n) printf("%d", n - 1);
    else printf("%d", Ans);
}
int main() {
    return build(1, 1, MAX), build(), solve(), 0;
}