BZOJ 3676字符串:PAM练习

题意:

给出一个字符串,求

S[i,j]S[i,j](ji+1) ∑ S [ i , j ] 为 回 文 串 S [ i , j ] 出 现 次 数 ∗ ( j − i + 1 )

题解:

构造出这个串的PAM,然后拓扑统计出每个状态的出现次数,然后扫一遍得到答案。注意long long。
Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+100;
struct Palindromic_AutoMachine{
    int fail[maxn],nxt[maxn][26],l[maxn],num[maxn],last,cnt,now;
    int S[maxn];
    inline void init(){
        S[0]=-1;
        now =1;
        fail[0]=cnt=1;
        last = l[0] = 0;
        l[1] =-1;
        memset(nxt,0,sizeof nxt[0]);
        memset(nxt,0,sizeof nxt[1]);
    }
    Palindromic_AutoMachine(){
        init();
    }
    inline int newnode(int ll){
        cnt++;
        memset(nxt[cnt],0,sizeof nxt[cnt]);
        fail[cnt]=0;num[cnt]=0;l[cnt]=ll;
        return cnt;
    }
    inline int get_fail(int x){
        while (S[now-l[x]-2]!=S[now-1])x = fail[x];
        return x;
    }
    void add(int ch){
        S[now++] =ch;
        int cur = get_fail(last);
        if(!nxt[cur][ch]){
            int tt = newnode(l[cur]+2);
            fail[tt] = nxt[get_fail(fail[cur])][ch];
            nxt[cur][ch] = tt;
        }
        last = nxt[cur][ch];num[last]++;
    }
    long long count(){
        long long ret =1;
        for (int i=cnt;i>=2;i--){
            num[fail[i]]+=num[i];
            ret = max(ret,1LL*l[i]*num[i]);
        }
        num[0]=num[1]=0;
        return ret;
    }
}pam;
char s[maxn];
int main(){
    scanf("%s",s+1);
    int len =strlen(s+1);
    for (int i=1;i<=len;i++){
        pam.add(s[i]-'a');
    }
    printf("%lld\n",pam.count());
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值