[BZOJ3679][Apio2014]回文串

[Apio2014]回文串

Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
【样例输入l】
abacaba
【样例输入2]
www
Sample Output
【样例输出l】
7
【样例输出2]
4
HINT
一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中:
● a出现4次,其出现值为4:1:1=4
● b出现2次,其出现值为2:1:1=2
● c出现1次,其出现值为l:1:l=l
● aba出现2次,其出现值为2:1:3=6
● aca出现1次,其出现值为1=1:3=3
●bacab出现1次,其出现值为1:1:5=5
● abacaba出现1次,其出现值为1:1:7=7
故最大回文子串出现值为7。
【数据规模与评分】
数据满足1≤字符串长度≤300000。

Solution
回文自动机。
三大自动机已经集齐。

Code


#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define REP(i, n) for (int i = 0; i < (n); i++)
#define PER(i, n) for (int i = (n)-1; i; i--)
#define MS(_) memset(_, 0, sizeof(_))
#define MP make_pair
#define PB push_back
typedef long long ll;
template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
    while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
    x *= f;
}
template<typename T> inline void ckmax(T &a, T b){ if (a < b) a = b; }
template<typename T> inline void ckmin(T &a, T b){ if (a > b) a = b; }

const int MaxN = 300010;
int n, fail[MaxN], nxt[MaxN][26], sz[MaxN];
ll len[MaxN], ans;
char str[MaxN];

struct PAM{
    int cnt, last;
    PAM(){ cnt = 1; fail[0] = fail[1] = 1; len[1] = -1; }
    inline void ins(int c, int n){
        int p = last;
        for(; str[n-len[p]-1] != str[n]; p = fail[p]);
        if (!nxt[p][c]){
            int now = ++cnt, k = fail[p];
            len[now] = len[p] + 2;
            for (; str[n-len[k]-1] != str[n]; k = fail[k]);
            fail[now] = nxt[k][c]; nxt[p][c] = now;
        }
        last = nxt[p][c]; sz[last]++;
    }
    inline void build(){
        scanf("%s", str+1); n = strlen(str+1);
        rep(i, 1, n) ins(str[i]-'a', i);
    }
    inline void solve(){
        per(i, cnt, 1) sz[fail[i]] += sz[i], ckmax(ans, 1ll*sz[i]*len[i]);
    }
}pam;
int main(){
    pam.build();
    pam.solve();
    printf("%lld\n", ans);
    return 0;
}

你可能感兴趣的:(回文自动机)