码迷,mamicode.com
首页 > 其他好文 > 详细

回文自动机入门题

时间:2019-07-30 21:54:04      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:style   onclick   print   定义   hid   整数   数据   ada   closed   

 

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

 

回文自动机入门题

标签:style   onclick   print   定义   hid   整数   数据   ada   closed   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!