码迷,mamicode.com
首页 > 其他好文 > 详细

P4555 [国家集训队]最长双回文串

时间:2018-09-08 19:22:29      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:位置   oid   amp   dtree   nbsp   scan   题意   line   struct   

题意:求这样一个回文串S,S = A + B 且 A, B都是回文串。问最长S

题解:建立两颗回文树,一个从前向后插,一个从后向前插,并记录每个位置得到的最长后缀后文。

ps:马拉车的做法待更

const int N = 100005;

struct data {
    int len, fail;
    int ch[26];
};

struct PldTree {
    int tot, last;
    int cnt[N];

    char s[N];
    data node[N];

    void Inite() {
        tot = last = 1;
        node[0].fail = 1;
        node[1].len = -1;
    }
    void Insert(int i) {
        while(s[i] != s[i - node[last].len - 1]) last = node[last].fail;
        if (!node[last].ch[s[i] - a]) {
            node[++tot].len = node[last].len + 2;
            cnt[i] = node[tot].len;

            int tp = node[last].fail;
            while(s[i] != s[i - node[tp].len - 1]) tp = node[tp].fail;

            node[tot].fail = node[tp].ch[s[i] - a];
            node[last].ch[s[i] - a] = tot;
            last = tot;
        }
        else {
            last = node[last].ch[s[i] - a];
            cnt[i] = node[last].len;
        }
    }
};

PldTree T1, T2;

inline void upd(int &a, int b) {
    (a < b) && (a = b);
}

int main()
{
    T1.Inite();
    T2.Inite();

    T1.s[0] = T2.s[0] = 0;

    scanf("%s", T1.s + 1);

    int n = strlen(T1.s + 1);
    Rep(i, 1, n) {
        T2.s[i] = T1.s[n + 1 - i];
        T1.Insert(i);
    }

    Rep(i, 1, n) {
        T2.Insert(i);
    }

    int ans = 0;
    Rep(i, 1, n) upd(ans, T1.cnt[i] + T2.cnt[n - i]);

    pr(ans);
    return 0;
}

 

P4555 [国家集训队]最长双回文串

标签:位置   oid   amp   dtree   nbsp   scan   题意   line   struct   

原文地址:https://www.cnblogs.com/zgglj-com/p/9610092.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!