• P3649 [APIO2014]回文串


    思路

    回文自动机

    回文自动机的fail[i]就是编号为i的这个字符串的最长的回文后缀的编号,然后len[i]表示编号为i的回文串的长度,cnt[i]表示编号为i的回文串的出现次数
    然后trans边就是同时在两边加上一个字符,fail边就是跳fail
    然后初始有一个0节点,len为0,fail[0]=1,s[0]=-1,表示长度为2的回文串(s[i-1]和s[i]),另一个1节点,len=-1,表示长度为1的回文串(s[i]自身)
    然后跳fail就是比较s[i-len[p]-1]==s[i],满足证明找到了,否则继续往上跳
    然后子节点的fail就是它父亲的fail的对应转移边(类似AC自动机
    然后就没有了

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 300010;
    int len[MAXN],cnt[MAXN],fail[MAXN],trans[MAXN][26],s[MAXN],Nodecnt,last,n;
    char S[MAXN];
    long long ans=0;
    int New_state(int _len){
        len[Nodecnt]=_len;
        return Nodecnt++;
    }
    int get_fail(int p,int n){
        while(s[n-len[p]-1]!=s[n])
            p=fail[p];
        return p;
    }
    void add_len(int n){
        int cur=get_fail(last,n);
        if(!trans[cur][s[n]]){
            int t=New_state(len[cur]+2);
            fail[t]=trans[get_fail(fail[cur],n)][s[n]];
            trans[cur][s[n]]=t;
        }
        cnt[trans[cur][s[n]]]++;
        last=trans[cur][s[n]];
    }
    int main(){
        s[0]=-1;
        New_state(0);
        fail[0]=1;
        New_state(-1);
        last=0;
        scanf("%s",S+1);
        n=strlen(S+1);
        for(int i=1;i<=n;i++){
            s[i]=S[i]-'a';
            add_len(i);
        }
        for(int i=Nodecnt-1;i>=0;i--)
            cnt[fail[i]]+=cnt[i];
        for(int i=0;i<Nodecnt;i++)
            ans=max(ans,1LL*cnt[i]*len[i]);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Java多态
    24系列EEPROM应用注意事项
    EEPROM读写问题
    EEPROM读写操作常见的陷阱
    MPLAB X IDE使用心得
    PIC18系列单片机I/O端口操作寄存器及应用
    IAR使用printf()函数 打印输出
    0欧电阻作用
    IAR MSP430设置合理堆栈大小(the stack pointer for stack is outside the stack range)
    MSP430教程14:MSP430单片机ADC12模块
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10638676.html
Copyright © 2020-2023  润新知