现在的位置: 首页 > 综合 > 正文

UVALive 4975 Casting Spells

2012年08月04日 ⁄ 综合 ⁄ 共 1419字 ⁄ 字号 评论关闭

UVALive_4975

    可以先用Manacher算法预处理出每个字符i处的回文半径Ri,也就是最大的Ri使得i-Ri~i+Ri-1构成回文串。

    之后枚举每个字符i作为wwRwwR中后面这个的wwR的起始字符,然后在[i-Ri/2,i-1]的范围内找到最小的j使得j+Rj>=i,如果存在这样的j,那么就存在一个长度为4*(i-j)的wwRwwR式的回文串。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXD 300010
int L, N, D, p[2 * MAXD], r[MAXD], tree[4 * MAXD];
char str[MAXD], b[2 * MAXD];
struct St
{
    int id, v;
    St(){}
    St(int _id, int _v) : id(_id), v(_v){}
    bool operator < (const St &t) const
    {
        return v > t.v;
    }
};
void prep()
{
    int i, id, max = 0;
    for(i = 0; str[i]; i ++) b[2 * i + 1] = '#', b[2 * i + 2] = str[i];
    L = i, N = 2 * i + 1;
    b[0] = '$', b[N] = b[N + 1] = '#';
    for(i = 1; i <= N; i ++)
    {
        p[i] = i < max ? std::min(max - i, p[2 * id - i]) : 1;
        while(b[i + p[i]] == b[i - p[i]]) ++ p[i];
        if(i + p[i] > max) max = i + p[i], id = i;
    }
    for(i = 0; i < L; i ++) r[i] = (p[2 * i + 1] - 1) / 2;
}
void init()
{
    int i, j;
    scanf("%s", str);
    prep();
}
void update(int i)
{
    for(; i ^ 1; i >>= 1) tree[i >> 1] = std::min(tree[i], tree[i ^ 1]);
}
int query(int x, int y)
{
    int i = D + x - 1, j = D + y + 1, ans = INF;
    for(; i + 1 != j; i >>= 1, j >>= 1)
    {
        if(~i & 1) ans = std::min(ans, tree[i ^ 1]);
        if(j & 1) ans = std::min(ans, tree[j ^ 1]);
    }
    return ans;
}
void solve()
{
    int i, j, ans = 0;
    for(D = 1; D < L + 2; D <<= 1);
    memset(tree, 0x3f, sizeof(tree[0]) * 2 * D);
    std::priority_queue <St> q;
    for(i = 0; i < L; i ++)
    {
        while(!q.empty())
        {
            St st = q.top();
            if(st.v >= i) break;
            q.pop(), tree[D + st.id] = INF, update(D + st.id);
        }
        q.push(St(i, i + r[i])), tree[D + i] = i, update(D + i);
        if(r[i] < 2) continue;
        j = query(i - r[i] / 2, i - 1);
        if(j != INF) ans = std::max(ans, 4 * (i - j));
    }
    printf("%d\n", ans);
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t --)
    {
        init();
        solve();
    }
    return 0;
}

 

 

抱歉!评论已关闭.