您的位置:首页 > 其它

BZOJ 3676 [Apio2014]回文串 回文自动机

2017-04-04 20:14 387 查看
题目大意:在一个串中一个子串的权值被定义为在串中的出现次数乘以子串长度,求所有回文子串的最大权值

貌似要用后缀自动机+manacher+倍增,然而有了回文自动机就成了裸题..

这里引用一下别人的文章 Palindromic Tree——回文树【处理一类回文串问题的强力工具】

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 300005
using namespace std;
typedef long long LL;
struct Node {
Node *ch[27],*fail;
int val,cnt;
Node() {}
Node(int _val):val(_val) {}
void* operator new(size_t) {
static Node *C,*mempool;
if(C==mempool) mempool=(C=new Node[1<<20])+(1<<20);
return C++;
}
}*root,*last;
void extend(int x,char s[]) {
Node* p=last;
while(s[x-2*p->val]!=s[x]) p=p->fail;
Node*& q=p->ch[s[x]-'`'];
if(q) last=q;
else {
last=q=new Node(p->val+1);
for(p=p->fail;p;p=p->fail)
if(s[x-2*p->val]==s[x]) {
last->fail=p->ch[s[x]-'`'];
break;
}
if(!p) last->fail=root;
}
last->cnt++;
return ;
}
void init(char str[]) {
static char s[N*2];
last=root;
int n=strlen(str+1),len=n*2+1;
for(int i=len;i;i--)
if(i&1) s[i]='`';
else s[i]=str[i/2];
for(int i=1;i<=len;i++) extend(i,s);
return ;
}
LL calc() {
static Node* q[N*2];
int l,r;
l=r=0;
LL ans=0;
q[r++]=root;
while(l<r) {
Node* tmp=q[l++];
for(int i=0;i<27;i++)
if(tmp->ch[i])
q[r++]=tmp->ch[i];
}
for(int i=r-1;i;i--) {
Node* tmp=q[i];
tmp->fail->cnt+=tmp->cnt;
ans=max(ans,(LL)(tmp->val-1)*tmp->cnt);
}
return ans;
}
int main() {
root=new Node(0);
static char str
;
scanf("%s",str+1);
init(str);
printf("%lld\n",calc());
//printf("%c",'a'-1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: