[Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)
2018-04-12 14:53
399 查看
3676: [Apio2014]回文串
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 3396 Solved: 1568
[Submit][Status][Discuss]
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
【样例输入l】
abacaba
【样例输入2]
www
Sample Output
【样例输出l】
7
【样例输出2]
4
HINT
一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中:
● a出现4次,其出现值为4:1:1=4
● b出现2次,其出现值为2:1:1=2
● c出现1次,其出现值为l:1:l=l
● aba出现2次,其出现值为2:1:3=6
● aca出现1次,其出现值为1=1:3=3
●bacab出现1次,其出现值为1:1:5=5
● abacaba出现1次,其出现值为1:1:7=7
故最大回文子串出现值为7。
【数据规模与评分】
数据满足1≤字符串长度≤300000。
分析:
回文树眼题,但是我不会回文树QAQ于是后缀自动机加manacher,构造出后缀自动机parent树后倍增每个点2^i能到达的点的dis值。 然后就可以做了。。。
AC代码:
# include <iostream> # include <cstdio> # include <cstring> using namespace std; const int N = 3e5 + 12; long long ans; int ch[N << 1][26]; int dis[N << 1],fa[N << 1],w[N << 1],cnt = 1,len; int que[N << 1],p[N << 1],dt,Log[19],g[N << 1][19],Id ; char str ,s[N << 1]; int Sam(int c,int last) { int u = last,cur; while(u && !ch[u][c])que[++que[0]] = u,u = fa[u]; if(!u) { cur = ++cnt;fa[cur] = 1; while(que[0])ch[que[que[0]--]][c] = cur; } else { int v = ch[u][c]; if(dis[v] == dis[u] + 1) { cur = ++cnt;fa[cur] = v; while(que[0])ch[que[que[0]--]][c] = cur; } else { int av = ++cnt;dis[av] = dis[u] + 1;cur = ++cnt; while(que[0])ch[que[que[0]--]][c] = cur; memcpy(ch[av],ch[v],sizeof ch[v]); fa[av] = fa[v];fa[v] = fa[cur] = av; while(u && ch[u][c] == v)ch[u][c] = av,u = fa[u]; } } dis[cur] = dis[last] + 1; return cur; } void Manacher() { s[0] = '$';s[dt = 1] = '#'; for(int i = 1;i <= len;i++)s[++dt] = str[i],s[++dt] = '#'; int mx = 2,id = 1;p[0] = p[1] = 0; for(int i = 2;i < dt;i++) { p[i] = min(p[2 * id - i],mx - i); while(s[i + p[i] + 1] == s[i - p[i] - 1]) { p[i]++; if((i + p[i]) & 1) { int now = Id[(i + p[i] - 1) >> 1],L = ((i + p[i] - 1) >> 1) - ((i - p[i] + 1) >> 1) + 1; for(int j = 18;~j;j--)if(dis[g[now][j]] >= L)now = g[now][j]; ans = max(ans,1LL * L * w[now]); } } if(i + p[i] > mx) { id = i; mx = i + p[i]; } } } void init() { Log[0] = 1;for(int i = 1;i < 19;i++)Log[i] = Log[i - 1] << 1; for(int i = 1;i <= cnt;i++)g[i][0] = fa[i];//这里考场上写成了<=len,结果得了90 for(int j = 1;j <= 18;j++) for(int i = 1;i <= cnt;i++) g[i][j] = g[g[i][j - 1]][j - 1]; } int main() { scanf("%s",str + 1);len = strlen(str + 1);Id[0] = 1; for(int i = 1;i <= len;i++)Id[i] = Sam(str[i] - 'a',Id[i - 1]),w[Id[i]]++; for(int i = 1;i <= cnt;i++)p[dis[i]]++; for(int i = 1;i <= len;i++)p[i] += p[i - 1]; for(int i = cnt;i >= 1;i--)que[p[dis[i]]--] = i; for(int i = cnt;i >= 1;i--)w[fa[que[i]]] += w[que[i]]; init();Manacher(); printf("%lld\n",ans); return 0; }
相关文章推荐
- bzoj 3676: [Apio2014]回文串 manachar+后缀自动机+倍增(回文树)
- [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增
- 【bzoj3676】[Apio2014]回文串 后缀自动机
- [BZOJ3676][Apio2014]回文串-后缀自动机+Manacher | | 回文树
- [manacher 后缀自动机 || 回文自动机] BZOJ 3676 [Apio2014]回文串
- bzoj 3676: [Apio2014]回文串【后缀自动机+manacher】
- BZOJ3676 APIO2014回文串(manacher+后缀自动机)
- [BZOJ]3676: [Apio2014]回文串 回文自动机
- BZOJ3676:[Apio2014]回文串(回文自动机)
- bzoj 3676: [Apio2014]回文串 回文自动机
- [回文自动机] BZOJ 3676: [Apio2014]回文串
- BZOJ 3676 [Apio2014]回文串 回文自动机
- 回文自动机 模板 bzoj3676【Apio2014】回文串
- 字符串(马拉车算法,后缀数组,稀疏表):BZOJ 3676 [Apio2014]回文串
- BZOJ 3676: [Apio2014]回文串 回文自动机
- BZOJ 3676: [Apio2014]回文串 回文串自动机
- bzoj 3676: [Apio2014]回文串 -- 回文自动机
- [bzoj3676][Apio2014]回文串 回文自动机(回文树)
- 【APIO2014】回文串 jzoj 3654/洛谷 3649/bzoj 3676 回文树(回文自动机)
- 【bzoj3676】[Apio2014]回文串 —— 回文自动机的学习