回文串[APIO2014](回文树)

2021-03-20 14:24

阅读:333

4

首先建出s的回文树,然后对于每一个回文子串,记录cnt为它出现的次数。

对于它fail树上的儿子,肯定都是它的子串(后缀),所以他出现了cnt次,它的后缀也会出现cnt次。

我们从更新的节点从后往前遍历,假设现在遍历到i,就使cnt[fail[i]]+=cnt[i]。然后更新ans=max(ans, cnt[i]*len[i])。

#include 
#include 
#include using namespace std;
const int N = 400000;
char s[N];
int lens;
long long ans;
namespace Plalindromic_Tree{
    struct node{
        int go[26];
        int fail, len;
    }pt[N];
    int lst = 0, tot = 0;
    int cnt[N];
    void build() {
        s[0] = -1;
        pt[++tot].len = -1;
        pt[0].fail = pt[1].fail = 1;
    }
    void add(int c, int n) {
        int p = lst;
        while (s[n - pt[p].len - 1] != s[n]) p = pt[p].fail;
        if (!pt[p].go[c]) {
            int v = ++tot, k = pt[p].fail;
            pt[v].len = pt[p].len + 2;
            while (s[n - pt[k].len - 1] != s[n]) k = pt[k].fail;
            pt[v].fail = pt[k].go[c];
            pt[p].go[c] = v;
        }
        lst = pt[p].go[c];
        cnt[pt[p].go[c]]++;
    }
}using namespace Plalindromic_Tree;
int main() {
    scanf("%s", s + 1);
    lens = strlen(s + 1);
    build();
    for (int i = 1; i ) {
        add(s[i] - a, i);
    }
    for (int i = tot; i; i--) {
        cnt[pt[i].fail] += cnt[i];
        ans = max(ans, 1ll * cnt[i] * pt[i].len);
    }
    cout  ans;
    return 0;
}
 


评论


亲,登录后才可以留言!