Codeforces 932G Palindrome Partition - 回文树 - 动态规划
题目传送门
通往???的传送点
通往神秘地带的传送点
通往未知地带的传送点
题目大意
给定一个串$s$,要求将$s$划分为$t_{1}t_{2}\cdots t_{k}$,其中$2\mid k$,且$t_{i} = t_{k - i}$,问方案数。
直接做不太好做。虽然可以$O(n^{2})$进行动态规划。
考虑做一步转化:设$s' = s_{1}s_{n}s_{2}s_{n - 1}\cdots s_{n / 2}s_{n / 2 + 1}$。
然后它的一个偶回文划分可以和原来的划分一一对应。
于是可以$O(n^{2})$进行动态规划。然后完美TLE。
定理1 一个回文的后缀是回文串当且仅当它是原串的border。
根据回文串和border的定义容易证明。
引理1 (Weak Periodicity Lemma) 设$p$和$q$是$s$的周期,且$p + q \leqslant |s|$,则$(p, q)$也是$s$的周期
证明 不妨设$p < q, d = q - p$。
- 当$|s| - q\leqslant i \leqslant |s| - d$时,$s_{i} = s_{i - p} = s_{i - p + q} = s_{i + d}$
- 当$1\leqslant i < |s| - q$时,$s_{i} = s_{i + q} = s_{i + q - p} = s_{i + d}$。
然后根据辗转相除法能够得到$(p, q)$也是$s$的周期。因此定理得证。
引理2 字符串的所有长度不小于$|s| / 2$的所有border的长度构成等差数列。
证明 设$|s| - p (p\leqslant |s| / 2)$是$s$最长的$border$,另外某个border的长度是:$|s| - q (q\leqslant |s| / 2)$,那么能够推出$(p, q)$是$s$的周期,因此$|s| - (p, q)$也是字符串$s$的border。由$p$的最小性以及$(p, q)\leqslant p$可知$(p, q) = p$,即$p\mid q$。

(懒得画图了,直接截论文的图)
不难证明对于任意$q (q\leqslant |s| / 2)$,且$p\mid q$的后缀是字符串$s$的border。
推论 一个字符串的border可以被分为不超过$\left \lceil log_{2}n \right \rceil$段等差数列。
证明 设$2^{k}\leqslant n < 2^{k + 1}$,考虑以下几段的border:
$\begin{matrix}[2^{k}, n]\\ [2^{k - 1}, s^{k})\\ [2^{k - 2}, 2^{k - 1})\\ \vdots \\ [1, 2)\end{matrix}$
根据引理2可得长度属于每一段的border都是一个等差数列。
因此得证。
有了这个推论有什么用呢?

对于每一类border,每一次它被成为当前前缀的border意味着当前串的长度减去周期后,这些border还被发现了一次。
如上图,每次如果能够预处理出橙色部分,转移的时候只用补上没有计算的一项就好了.
用$f[i]$表示第$i$个前缀的偶回文划分的方案数。
用$g[i]$表示在回文树的状态$i$作为等差数列末项的时候等差border的动态规划的值的和。
建回文树的时候记一下dif和slink就可知道等差数列的差以及上一类等差数列的末项。
Code
/**
* Codeforces
* Problem#932G
* Accepted
* Time: 93ms
* Memory: 128200k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; const int alpha = ; typedef class TrieNode {
public:
int len, dif, g;
TrieNode *ch[alpha];
TrieNode *fail, *slink;
}TrieNode; typedef class PalindromeTree {
public:
int len;
TrieNode *pool;
TrieNode *top;
TrieNode *odd, *even;
TrieNode *last;
char *str; TrieNode* newnode(int len) {
top->len = len, top->dif = -, top->g = ;
memset(top->ch, , sizeof(top->ch));
top->fail = top->slink = NULL;
return top++;
} PalindromeTree() { }
PalindromeTree(int n) {
pool = new TrieNode[(n + )];
str = new char[(n + )];
top = pool, len = ;
odd = newnode(-), even = newnode();
odd->fail = odd, even->fail = odd;
odd->dif = even->dif = -, last = even, str[] = ;
} TrieNode* extend(TrieNode* p) {
while (str[len - p->len - ] != str[len]) p = p->fail;
return p;
} void append(char x) {
str[++len] = x;
int c = x - 'a';
last = extend(last);
if (!last->ch[c]) {
TrieNode* p = newnode(last->len + );
p->fail = extend(last->fail)->ch[c];
if (!p->fail)
p->fail = even;
last->ch[c] = p;
p->dif = p->len - p->fail->len; if (p->dif == p->fail->dif)
p->slink = p->fail->slink;
else
p->slink = p->fail;
}
last = last->ch[c];
}
}PalindromeTree; const int M = 1e9 + ; int n;
char bstr[], str[];
PalindromeTree pt;
int *f; inline void init() {
gets(bstr + );
n = strlen(bstr + );
for (int i = ; i <= n; i++) {
if (i & )
str[i] = bstr[(i + ) >> ];
else
str[i] = bstr[n - (i >> ) + ];
}
f = new int[(n + )];
memset(f, , sizeof(int) * (n + ));
} inline void solve() {
pt = PalindromeTree(n);
f[] = ;
for (int i = ; i <= n; i++) {
pt.append(str[i]);
for (TrieNode* p = pt.last; p && p->len > ; p = p->slink) {
p->g = f[i - p->slink->len - p->dif]; if (p->fail->dif == p->dif)
p->g = (p->g + p->fail->g) % M;
if (!(i & ))
f[i] = (f[i] + p->g) % M;
}
}
printf("%d", f[n]);
} int main() {
init();
solve();
return ;
}
Codeforces 932G Palindrome Partition - 回文树 - 动态规划的更多相关文章
- 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 ...
- CF932G Palindrome Partition(回文自动机)
CF932G Palindrome Partition(回文自动机) Luogu 题解时间 首先将字符串 $ s[1...n] $ 变成 $ s[1]s[n]s[2]s[n-1]... $ 就变成了求 ...
- Palisection(Codeforces Beta Round #17E+回文树)
题目链接 传送门 题意 给你一个串串,问你有多少对回文串相交. 思路 由于正着做不太好算答案,那么我们考虑用总的回文对数减去不相交的回文对数. 而不相交的回文对数可以通过计算以\(i\)为右端点的回文 ...
- HDU 6599 I Love Palindrome String (回文树+hash)
题意 找如下子串的个数: (l,r)是回文串,并且(l,(l+r)/2)也是回文串 思路 本来写了个回文树+dfs+hash,由于用了map所以T了 后来发现既然该子串和该子串的前半部分都是回文串,所 ...
- 【CF932G】Palindrome Partition 回文自动机
[CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_ ...
- 2019牛客暑期多校训练营(第六场)Palindrome Mouse 回文树+dfs
题目传送门 题意:给出一个字符串,将字符串中所有的回文子串全部放入一个集合里,去重后.问这个集合里有几对<a,b>,使得a是b的子串. 思路:一开始想偏了,以为只要求每个回文串的回文后缀的 ...
- @codeforces - 932G@ Palindrome Partition
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个字符串 s,求有多少种方案可将其划分成偶数个段 \(p_ ...
- Palindrome Partition CodeForces - 932G 回文树+DP+(回文后缀的等差性质)
题意: 给出一个长度为偶数的字符串S,要求把S分成k部分,其中k为任意偶数,设为a[1..k],且满足对于任意的i,有a[i]=a[k-i+1].问划分的方案数. n<=1000000 题解: ...
- 【CF932G】Palindrome Partition(回文树,动态规划)
[CF932G]Palindrome Partition(回文树,动态规划) 题面 CF 翻译: 给定一个串,把串分为偶数段 假设分为了\(s1,s2,s3....sk\) 求,满足\(s_1=s_k ...
随机推荐
- STM32进入HardFault_Handler处理办法
STM32进入HardFault_Handler处理办法 HardFault_Handler出现的情况一般有两种: 一种是:数组越界 一种是:堆栈溢出,程序指针指飞 方法一 在中断HardFault_ ...
- 【CF429E】Points and Segments 欧拉回路
[CF429E]Points and Segments 题意:给你数轴上的n条线段$[l_i,r_i]$,你要给每条线段确定一个权值+1/-1,使得:对于数轴上的任一个点,所有包含它的线段的权值和只能 ...
- windows系统关闭某个端口的服务(以443端口为例子)
1.查看443被什么服务占用 netstat -ano | findstr 443 查看到443端口被pid为5140的服务占用了 2.去到任务管理器->任务 找到PID为5140的服务,然后停 ...
- poj 2420
太虚假了. 我为什么要手贱点开submission? 这道题两天之前被一个学弟A了. ? 我退役了. 其实就是爬山吧..好像有的题解还分方向什么的完全没必要吧. #include <iostre ...
- SQL Server 将查询结果导出插入的简单方式
https://blog.csdn.net/danny_style/article/details/45166391 1.首先将查询结果添加到一个原数据库中不存在的表,表名随意命名. 例: selec ...
- MVC的HTTP请求处理过程(IIS应用程序池、CLR线程池)
主要内容 本文讲解的是:服务器接受Http Request请求之后,是如何进入.Net CLR,从而进一步操作的. 我们大家都知道,IIS必须先接受请求,然后才能有机会进入CLR,但对请求(reque ...
- [No0000193]Chrome浏览器控制台(console)花式调试
对前端开发者来说,Chrome Dev Tools(开发者工具,以下简称CDT)是一个不可或缺的开发调试工具,但是你可能只用过console.log(),却不知道console还有很多功能强大的调试方 ...
- stm32专属于菜鸟的学习方法
1.首先我们先看看与STM32相关的文档 我们假定大家已经对STM32的书籍或者文档有一定的理解.如不理解,请立即阅读STM32的文档,以获取最基本的知识点. 如果你手上拥有ST官方主推的STM32神 ...
- [特征工程]-------使用sklearn做单机特征工程[转载]
https://www.cnblogs.com/jasonfreak/p/5448385.html 使用sklearn做单机特征工程 目录 1 特征工程是什么?2 数据预处理 2.1 无量纲化 2.1 ...
- JavaWeb & Tomcat
1 JavaWeb概述 Java在服务器端的应用有Servlet,JSP和第三方框架等. Java的Web框架基本都遵循特定的路数:使用Servlet或者Filter拦截请求,使用MVC的思想设计架构 ...