回文自动机入门题

Posted violet-acmer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回文自动机入门题相关的知识,希望对你有一定的参考价值。

 

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 
View Code

 

 

 


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秒
View Code

•题解

  枚举位置 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 
View Code

 

以上是关于回文自动机入门题的主要内容,如果未能解决你的问题,请参考以下文章

回文自动机做题小结

bzoj千题计划306:bzoj2342: [Shoi2011]双倍回文 (回文自动机)

bzoj千题计划304:bzoj3676: [Apio2014]回文串

Loj141. 回文子串

P3649 [APIO2014]回文串

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