BZOJ 3676字符串:PAM练习

题意:

给出一个字符串,求

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;
}

猜你喜欢

转载自blog.csdn.net/calabash_boy/article/details/80328123