bzoj 3676: [Apio2014]回文串 回文自动机

题目:

Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最 大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。

题解:

回文自动机裸题

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 300010;
struct Node{
    int nx[26];
    int len,fail,siz,num;
}T[maxn];
int last,nodecnt,str[maxn],len;
inline void init(){
    last = nodecnt = 0;
    T[++nodecnt].len = -1;
    str[len=0] = -1;
    T[0].fail = 1;
}
inline void insert(char cha){
    int c = cha - 'a',p,cur,x;str[++len] = c;
    for(p = last;str[len - T[p].len - 1] != str[len];p = T[p].fail);
    if(T[p].nx[c] == 0){
        T[cur = ++ nodecnt].len = T[p].len + 2;
        for(x = T[p].fail;str[len - T[x].len - 1] != str[len];x = T[x].fail);
        T[cur].fail = T[x].nx[c];T[p].nx[c] = cur;T[cur].num = T[T[cur].fail].num+1;
    }T[last = T[p].nx[c]].siz ++ ;
}
char s[maxn];
int main(){
    init();scanf("%s",s);int len = strlen(s);
    for(int i=0;i<len;++i) insert(s[i]);
    ll ans = 0;
    for(int i = nodecnt;i>=2;--i){
        if(T[i].fail) T[T[i].fail].siz += T[i].siz;
        ans = max(ans,1LL*T[i].siz*T[i].len);
    }printf("%lld\n",ans);
    getchar();getchar();
    return 0;
}
posted @ 2017-03-11 07:33  Sky_miner  阅读(196)  评论(0编辑  收藏  举报