[加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)
题目链接: https://codeforces.com/contest/835/problem/D
注: 欢迎移步 https://codeforces.com/blog/entry/67839
题意: 一个回文串是\(1\)-回文的,如果一个回文串的左半部分和右半部分一样且都是\(k\)-回文串(右半部分是指长度为该串长度除以二下取整的后缀),则该串为\((k+1)\)回文串,满足该串是\(k\)回文串的最大\(k\)称作该串的回文级别。给定一个串\(s\), 对于每一个\(k=1,2,...,n\)求出该串中有多少个位置不同的\(k\)-回文串。\(n\le 5\times 10^6\). (除数据范围外与原题均相同)
题解: \(n^2\)的做法肯定是以子串为状态进行dp, 但是显然废状态太多了,只有回文串dp值非零,而一个串本质不同的回文串的个数是\(O(n)\)的。
所以,以本质不同的回文串作为状态进行dp. 本质不同的回文串一一对应回文自动机上的节点。设\(f[x]\)表示\(x\)节点代表回文串的回文级别。
然后转移方程显然: 若\(x\)不存在长度为\([\frac{x}{2}]\)(中括号表示下取整)的回文后缀,则\(dp[x]=1\), 否则\(dp[x]\)等于那个回文后缀的\(dp\)值+1.
dp完之后,我们求的是本质不同,但是题目要求求位置不同,所以还需要再统计一下每个点的子树大小。
时间复杂度\(O(n)\).
代码 (Codeforces 835D AC)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
using namespace std;
const int N = 1e6+2;
const int LGN = 23;
const int S = 26;
int son[N+3][S+1];
int fail[N+3];
int len[N+3];
int sz[N+3];
int tsz[N+3];
char a[N+3];
int dp[N+3];
int bd[N+3];
int ord[N+3];
int buc[N+3];
llong ans[N+3];
int n,siz,lstpos;
void initPAM()
{
siz = lstpos = 1; fail[0] = fail[1] = 1; len[1] = -1; len[0] = 0; bd[0] = 0; bd[1] = 1;
}
void insertchar(int id)
{
int p = lstpos;
while(a[id]!=a[id-len[p]-1]) {p = fail[p];}
if(!son[p][a[id]])
{
siz++; int u = siz,v = fail[p];
while(a[id]!=a[id-len[v]-1]) {v = fail[v];}
fail[u] = son[v][a[id]]; son[p][a[id]] = u; len[u] = len[p]+2;
if(len[u]<=2) {bd[u] = fail[u];}
else
{
bd[u] = bd[p];
while(a[id]!=a[id-len[bd[u]]-1] || (len[bd[u]]+2)*2>len[u])
{
bd[u] = fail[bd[u]];
}
bd[u] = son[bd[u]][a[id]];
}
if(len[bd[u]]==(len[u]>>1)) {dp[u] = max(0,dp[bd[u]])+1;}
else {dp[u] = 1;}
}
sz[son[p][a[id]]]++;
lstpos = son[p][a[id]];
}
int main()
{
initPAM();
scanf("%s",a+1); n = strlen(a+1);
for(int i=1; i<=n; i++) a[i]-=96;
for(int i=1; i<=n; i++) {insertchar(i);}
for(int i=2; i<=siz; i++) {buc[len[i]]++;}
for(int i=1; i<=n; i++) {buc[i] += buc[i-1];}
for(int i=siz; i>=2; i--) {ord[(buc[len[i]]--)+1] = i;}
ord[0] = 1; ord[1] = 0;
for(int j=siz; j>=2; j--)
{
int u = ord[j];
sz[fail[u]] += sz[u];
}
for(int j=2; j<=siz; j++)
{
ans[dp[j]] += (llong)sz[j];
}
for(int j=LGN-1; j>=1; j--) ans[j] += ans[j+1];
for(int i=1; i<=n; i++) printf("%I64d\n",ans[i]);
return 0;
}
[加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)的更多相关文章
- 【XSY2534】【CF835D】Palindromic characteristics 回文自动机
题目大意 一个字符串\(s\)是\(1\)−回文串当且仅当这个串是回文串. 一个串\(s\)是\(k\)−回文串\((k>1)\)当且仅当\(s\)的前一半与后一半相同且\(s\)的前一 ...
- CodeForces 835D - Palindromic characteristics | Codeforces Round #427 (Div. 2)
证明在Tutorial的评论版里 /* CodeForces 835D - Palindromic characteristics [ 分析,DP ] | Codeforces Round #427 ...
- Palindromic Tree 回文自动机-回文树 例题+讲解
回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同 ...
- bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)
bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp) bzoj Luogu 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一 ...
- bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)
bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp) bzoj Luogu 你要用ATGC四个字母用两种操作拼出给定的串: 1.将其中一个字符 ...
- 洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)
传送门 回文自动机的好题啊 先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数 首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...
- bzoj 4044: [Cerc2014] Virus synthesis【回文自动机+dp】
建回文自动机,注意到一个回文串是可以通过一个长度小于等于这个串长度的一半的回文串添上一些字符然后复制得到的,也就是在自动机上向fa走,相当于treedp 每次都走显然会T,记录一个up,指向祖先中最下 ...
- [CERC2014]Virus synthesis【回文自动机+DP】
[CERC2014]Virus synthesis 初始有一个空串,利用下面的操作构造给定串 SS . 1.串开头或末尾加一个字符 2.串开头或末尾加一个该串的逆串 求最小化操作数, \(|S| \l ...
- Codeforces 932G Palindrome Partition 回文树+DP
题意:给定一个串,把串分为偶数段 假设分为$s_1,s_2,s_3....s_k$ 求满足$ s_1=s_k,s_2=s_{ k-1 }... $的方案数模$10^9+7$ $|S|\leq 10^6 ...
随机推荐
- regEx in Groovy
// 使用正则 得到非纯XML文件中的信息 // Response 经常得到的不是纯XML def pattern = ~/(<NewDataSet>).*(<\/NewDataSe ...
- POI 读取word (word 2003 和 word 2007)(转,好用)
POI 读取word (word 2003 和 word 2007)(转,好用) 转做的操作: 将作者文中失效的链接的正确链接放在失效链接的下面. 最近在给客户做系统的时候,用户提出需求,要能够导入 ...
- bzoj 3721 Final Bazarek
题目大意: n个数 选k个使和为奇数且最大 思路: 可以先将这n个数排序 然后先去最大的k个数 若和为奇数则直接输出 为偶数可以用没选的最大的奇数替换选了的最小的偶数或用没选的最大的偶数替换选了的最小 ...
- 洛谷 P2634 聪聪可可 —— 树形DP / 点分治
题目:https://www.luogu.org/problemnew/show/P2634 今天刚学了点分治,做例题: 好不容易A了,结果发现自己写的是树形DP...(也不用找重心)(比点分治快) ...
- C# Pen绘制虚线(System.Drawing.Pen与System.Windows.Media.Pen)
一.绘制虚线的方法 GDI绘制,使用的是System.Drawing.Pen Pen pen = new Pen(Color.Red, 1); pen.DashStyle = S ...
- Linux扩展正则表达式
1. 扩展正则表达式 1.1 +(加号) + 表示前一个字符出现1次或1次以上 1.1.1 理解+ 要求:取出文件内容连续出现的小写字母 [root@oldboyedu50-lnb /oldboy]# ...
- codevs1040统计单词个数(区间+划分型dp)
1040 统计单词个数 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给出一个长度不超 ...
- node.js的模块引用
1.模块的引用示例 var math = require(‘math’): 在common.js规范中,存在require()方法,这个方法接受模块标识,此引引入一个模块的api ...
- 题解报告:poj 3070 Fibonacci
题目链接:http://poj.org/problem?id=3070 Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, a ...
- android webview 简单应用
一直没有用过webView 在网上找了一个小例子,主要实现以下功能: 1.当webview加载网页的时候在标题栏上显示加载进度 2.隐藏webkit浏览器的地址栏 3.设置程序的标题为网页的标题 4. ...