回文自动机入门题

URAL-1960.Palindromes and Super Abilities

传送门

•题意

  给你一个长度为 n 的字符串 s,下标从 1 开始;

  输出 n 个数,第 i 个数表示 1~i 内有多少个本质不同的回文串;

•题解

  回文自动机入门题;

  定义 ans[ i ] 表示 1~i 共有 $ans_{i}$ 个本质不同的回文串;

  $ans_{i}=ans_{i-1}$+{第 i 个字符可形成本质不同的回文串 ? 1:0};

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+50;
 4
 5 char s[maxn];
 6 int ans[maxn];
 7
 8 struct PAM
 9 {
10     int tot;
11     int last;
12     int len[maxn];
13     int fail[maxn];
14     int son[maxn][30];
15
16     int newNode(int Len)
17     {
18         for(int i=0;i < 30;++i)
19             son[tot][i]=0;
20
21         fail[tot]=0;
22         len[tot]=Len;
23
24         return tot++;
25     }
26     int getFail(int p,int i)
27     {
28         while(s[i-len[p]-1] != s[i])
29             p=fail[p];
30
31         return p;
32     }
33     void Init()
34     {
35         tot=0;
36         last=0;
37
38         newNode(0);
39         newNode(-1);
40
41         fail[0]=1;
42     }
43     void pam()
44     {
45         Init();
46
47         int n=strlen(s);
48         for(int i=1;i < n;++i)
49         {
50             s[i]=s[i]-‘a‘+1;
51             int cur=getFail(last,i);
52
53             ans[i]=ans[i-1];
54             if(!son[cur][s[i]])
55             {
56                 int now=newNode(len[cur]+2);
57                 fail[now]=son[getFail(fail[cur],i)][s[i]];
58                 son[cur][s[i]]=now;
59
60                 ans[i]++;///如果可以形成本质不同的字符串,ans[i]=ans[i-1]+1;
61             }
62             last=son[cur][s[i]];
63         }
64     }
65 }_pam;
66 int main()
67 {
68     scanf("%s",s+1);
69     s[0]=‘#‘;
70     int n=strlen(s);
71
72     ans[0]=0;
73     _pam.pam();
74
75     for(int i=1;i < n;i++)
76         printf("%d%c",ans[i],i == n-1 ? ‘\n‘:‘ ‘);
77
78     return 0;
79 }


BZOJ-2565.最长双回文串

传送门

•题目描述

问题描述:
    顺序和逆序读起来完全一样的串叫做回文串。
    比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
  输入长度为n的串S,求S的最长双回文子串T;
    即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。

输入格式
  一行由小写英文字母组成的字符串S。

输出格式
  一行一个整数,表示最长双回文子串的长度。

样例输入
baacaabbacabb

样例输出
12

样例说明
  从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。

数据规模及限制
  对于10%的数据,2≤|S|≤103。
  对于30%的数据,2≤|S|≤104。
  对于100%的数据,2≤|S|≤105。
时间限制:2秒

•题解

  枚举位置 i,求出以第 i 个字符为结尾的最长的回文串长度 $x_i$ 和以第 i+1 个字符为开始的最长回文串长度 $y_{i+1}$;

  最终答案为 max{$x_{i}+y_{i+1}$};

  正向跑一边回文自动机便可求出以第 i 个字符为结尾的最长回文串的长度;

  反向跑一边回文自动机便可求出以第 i 个字符为开始的最长回文串的长度;

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+50;
 4
 5 string s;
 6
 7 ///a[0][i]:正向跑一边,求出以第i个字符为结尾的最长回文串的长度
 8 ///a[1][i]:反向跑一边,求出以第i个字符为开始的最长回文串的长度
 9 int a[2][maxn];
10
11 struct PAM
12 {
13     int tot;
14     int last;
15     int len[maxn];
16     int fail[maxn];
17     int son[maxn][30];
18
19     int newNode(int Len)
20     {
21         for(int i=0;i < 30;++i)
22             son[tot][i]=0;
23         len[tot]=Len;
24
25         return tot++;
26     }
27     int getFail(int p,int i)
28     {
29         while(s[i-len[p]-1] != s[i])
30             p=fail[p];
31
32         return p;
33     }
34     void Init()
35     {
36         tot=0;
37         last=0;
38
39         newNode(0);
40         newNode(-1);
41
42         fail[0]=1;
43     }
44
45     void pam(int k)
46     {
47         Init();
48
49
50         for(int i=1;i < s.size();++i)
51         {
52             s[i]=s[i]-‘a‘+1;
53             int cur=getFail(last,i);
54
55             if(!son[cur][s[i]])
56             {
57                 int now=newNode(len[cur]+2);
58                 fail[now]=son[getFail(fail[cur],i)][s[i]];
59                 son[cur][s[i]]=now;
60             }
61             last=son[cur][s[i]];
62
63             a[k][i]=len[last];
64         }
65     }
66 }_pam;
67 int main()
68 {
69     cin>>s;
70     s.insert(0,"#");
71
72     _pam.pam(0);
73     reverse(s.begin()+1,s.end());
74     _pam.pam(1);
75
76     int ans=0;
77     int n=s.size()-1;
78     for(int i=1;i < n;++i)
79         ans=max(ans,a[0][i]+a[1][n-i]);
80
81     printf("%d\n",ans);
82 }

原文地址:https://www.cnblogs.com/violet-acmer/p/11272790.html

时间: 2024-11-09 05:53:19

回文自动机入门题的相关文章

回文自动机刷题总结

最长双回文串 裸的回文自动机,将串reverse再插入一遍即可. 双倍回文 这题可以只维护偶回文串然后疯狂加特判判掉奇串 回文自动机,再多维护一个trans指针,指向trans[x]表示长度小于len[x]/2的最长的回文后缀 trans指针可以从父亲(不是fail)的trans指针求出. 其实还可以直接建完自动机后在fail树(即把fail指针当作父亲边构成的树)上开桶dfs 1 #include<bits/stdc++.h> 2 #define N 500050 3 using names

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

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

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 #defi

P3649 [APIO2014]回文串(回文自动机)

回文自动机裸题,把PAM建出来以后对每个节点更新答案即可 代码: #include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&

[BZOJ4044]Virus synthesis 回文自动机的DP

4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec  Memory Limit: 128 MB Description Viruses are usually bad for your health. How about fighting them with... other viruses? In this problem, you need to find out how to synthesize such good viruses. W

【XSY2715】回文串 树链剖分 回文自动机

题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(transl~l_1~r_1~l_2~r_2\):有两个\(s\)的子串\(s_1=s[l_1\ldots r_1],s_2=s[l_2\ldots r_2]\).你要把\(s_1\)变成\(s_2\).每次允许在左边加一个字符或删一个字符.要求操作次数最少.定义一个字符串是好的当且仅当这个字符串是回文串

「专题总结」回文自动机PAM

为了备课,把做完的专题的总结咕了这么久... 主要是自己做题做的太慢了,所以讲SAM的时候准备也不充分. 在把讲课时间不断咕之后依然是粗制滥造,锅很多,所以效果很差.而且还有人没听懂... 一半人都做了5道题以上了,另一半人还没怎么看,基本所有人都有预习. 得不到任何反馈,也不知道速度如何.就当凑活吧. 挺失败的.可能也没有下一次机会了. 我也不知道后缀数组推荐率是怎么达到100%的...那次我讲的自己也很满意 一到难的知识点我就不行了嘛...主要是自己理解也很不深刻 至少也还是在3个多小时之内

【回文自动机】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

回文树或者回文自动机,及相关例题

回文树简述 在大部分说法中,回文树与回文自动机指的是一个东西: 回文树是对一个字符串,基于自动机思想构建的处理回文问题的树形结构: 回文树是对着一个单串建立的: 于是他主要用于计数(回文子串种类及个数) 基本建立思路是先建立其前缀的回文树,然后每加上一个字符,统计影响: 回文树存在fail指针但一般不承接字符串匹配问题: (回文树大概可以判定一个回文串是不是一个串的子串,但KMP之类的可以做得更好) 构建好的回文树,是这样的: (好难看) 可看出: 存在两个树结构,分别记录奇数|偶数长度的回文: