hysbz3676 回文串 回文自动机

回文自动机模板题

头铁了一下午hdu6599,最后发现自己的板有问题

先放这里一个正确性得到基本确认的板,过两天肝hdu6599

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cassert>
#define MAXN 300010
#define LL long long
#define BASE 2LL
#define MOD 1000000007
using namespace std; 

char s[MAXN];
int len;
LL ans[MAXN];

int qpow(int base,int n){
    LL ans=1;
    while(n){
        if(n&1)ans=(ans*base)%MOD;
        base=(1LL*base*base)%MOD;
        n>>=1;
    }
    return ans;
}

struct PTnode{
    int len,fail,son[26];
    LL cnt;//该点对应的回文串出现次数
    //建完了树,要再跑一遍,cnt才是正确的
    PTnode(){
        cnt=len=fail=0;
        memset(son,0,sizeof son);
    }
}PTdian[MAXN<<1];

int PTlast,PTnum;

int PTgetfail(int i,int x){
    while(s[i-PTdian[x].len-1]!=s[i]) {
        x=PTdian[x].fail;
    }
    return x;
}

void PTextend(int i,int x){
    int cur=PTgetfail(i,PTlast);
    if(!PTdian[cur].son[x]){
        int now=++PTnum;
        PTdian[now].len=PTdian[cur].len+2;
        PTdian[now].fail=PTdian[PTgetfail(i,PTdian[cur].fail)].son[x];
        PTdian[cur].son[x]=now;
    }
    PTdian[PTdian[cur].son[x]].cnt++;
    PTlast=PTdian[cur].son[x];
}
void PTcount(){
    for(int i=PTnum;i>=2;i--){
        //逆序累加
        PTdian[PTdian[i].fail].cnt+=PTdian[i].cnt;
    }
}
//int dfs(int l,int index,int hash1,int hash2){
//    if(index>1 && hash1==hash2){
//        ans[PTdian[index].len]+=PTdian[index].cnt;
//    }
//    for(int i=0;i<26;i++){
//        if(PTdian[index].son[i]!=0){
//            LL tmp1=(hash1+i*qpow(BASE,l)%MOD)%MOD;
//            LL tmp2=(BASE*hash2%MOD+i)%MOD;
//            dfs(l+1,PTdian[index].son[i],tmp1,tmp2);
//        }
//    }
//}
//char a[MAXN];
//int dfs1(int depth,int index){
//    //检查回文自动机构造正确性
//    for(int i=0;i<depth;i++)printf("%c",a[i]);
//    printf(" len:%d siz:%d\n",PTdian[index].len,PTdian[index].cnt);
//    for(int i=0;i<26;i++){
//        if(PTdian[index].son[i]!=0){
//            a[depth]=i+‘a‘;
//            dfs1(depth+1,PTdian[index].son[i]);
//        }
//    }
//}
int main(){
//    freopen("1.txt","r",stdin);
//    freopen("2.txt","w",stdout);
    while(1){
        int rep=scanf("%s",s);
        if(rep==EOF)break;
        len=strlen(s);
        memset(ans,0,sizeof ans);memset(PTdian,0,sizeof PTdian);
        PTlast=PTnum=1;
        PTdian[1].len=-1;
        PTdian[0].fail=PTdian[1].fail=1;

        for(int i=0;i<len;i++){
            PTextend(i,s[i]-‘a‘);
        }
        PTcount();
        LL maxx=0;
        for(int i=2;i<=PTnum;i++){
            maxx=max(maxx,1LL*PTdian[i].cnt*PTdian[i].len);
        }
        printf("%lld\n",maxx);
//        dfs(0,0,0,0);
//        dfs(0,1,0,0);
    //    dfs1(0,0);
    //    dfs1(0,1);
//        for(int i=1;i<=len;i++)printf("%lld%c",ans[i],(i!=len)?‘ ‘:‘\n‘);
    } 

}

原文地址:https://www.cnblogs.com/isakovsky/p/11261531.html

时间: 2024-11-07 13:25:54

hysbz3676 回文串 回文自动机的相关文章

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

裸的回文串自动机 3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 504  Solved: 152 [Submit][Status][Discuss] Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的"出 现值"为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s

【bzoj3676】[Apio2014]回文串 回文自动机

题目描述 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最大出现值. 输入 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. 输出 输出一个整数,为逝查回文子串的最大出现值. 样例输入 [样例输入l] abacaba [样例输入2] www 样例输出 [样例输出l] 7 [样例输出2] 4 题解 回文自动机裸题 关于PAM个人暂时理解不是很深入,挖坑待填. 本题只需要统计fail树的子树大小,再

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

3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 844  Solved: 331[Submit][Status][Discuss] Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. Output 输出一个整数,

HYSBZ 3676 回文串 (回文树)

3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1680  Solved: 707 [Submit][Status][Discuss] Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的"出 现值"为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. Output

HYSBZ 2565 最长双回文串 (回文树)

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1377  Solved: 714 [Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y

P4555 [国家集训队]最长双回文串(回文树)

题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可将 T 分为两部分 X , Y ,( |X|,|Y|≥1 )且 X 和 Y都是回文串. 输入输出格式 输入格式: 一行由小写英文字母组成的字符串 S . 输出格式: 一行一个整数,表示最长双回文子串的长度. 输入输出样例 输入样例#1: 复制 baacaabbacabb 输出样例#1: 复制 12

bzoj3676: [Apio2014]回文串 回文树

回文树的裸题. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=500100; const int INF=1e9+10; struct PalinTree { int ch[maxn][26],f[maxn]; int

【回文自动机】bzoj3676 [Apio2014]回文串

回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i)代表个数(要最后在fail树上dp一遍方可). 答案直接枚举一遍结点,然后用len(i)*cnt(i),取最大者即可. 回文自动机是非常优越的数据结构,可惜比manacher多一个字符集的空间-- #include<cstdio> #include<cstring> #include

HDOJ 3948 The Number of Palindromes 回文串自动机

看上去像是回文串自动机的模板题,就来了一发 The Number of Palindromes Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1992    Accepted Submission(s): 694 Problem Description Now, you are given a string S. We want