CodeForces 17E Palisection(回文树)
2 seconds
128 megabytes
standard input
standard output
In an English class Nick had nothing to do at all, and remembered about wonderful strings called palindromes. We should remind you that a string is called a palindrome if it can be read the same
way both from left to right and from right to left. Here are examples of such strings: «eye», «pop»,
«level», «aba», «deed»,
«racecar», «rotor», «madam».
Nick started to look carefully for all palindromes in the text that they were reading in the class. For each occurrence of each palindrome in the text he wrote a pair — the position of the beginning and the position of the ending of this occurrence in the text.
Nick called each occurrence of each palindrome he found in the text subpalindrome. When he found all the subpalindromes, he decided to find out how many different pairs among these subpalindromes
cross. Two subpalindromes cross if they cover common positions in the text. No palindrome can cross itself.
Let's look at the actions, performed by Nick, by the example of text «babb». At first he wrote out all subpalindromes:
• «b» — 1..1
• «bab» — 1..3
• «a» — 2..2
• «b» — 3..3
• «bb» — 3..4
• «b» — 4..4
Then Nick counted the amount of different pairs among these subpalindromes that cross. These pairs were six:
1. 1..1 cross with 1..3
2. 1..3 cross with 2..2
3. 1..3 cross with 3..3
4. 1..3 cross with 3..4
5. 3..3 cross with 3..4
6. 3..4 cross with 4..4
Since it's very exhausting to perform all the described actions manually, Nick asked you to help him and write a program that can find out the amount of different subpalindrome pairs that cross. Two subpalindrome pairs are regarded as different if one of the
pairs contains a subpalindrome that the other does not.
The first input line contains integer n (1 ≤ n ≤ 2·106)
— length of the text. The following line contains n lower-case Latin letters (from ato z).
In the only line output the amount of different pairs of two subpalindromes that cross each other. Output the answer modulo 51123987.
4
babb
6
2
aa
2
给你一个串让你求,所有相交的回文子串对的个数
我们可以利用回文树求出以s[i]为结尾的回文子串个数Ai,和以s[i]为开始的的回文串个数Bi
那么不相交的回文子串对就是Ai*sum{Bi+1,Bi+2,Bi+3....Bi+n} {i=1..n-1};
然后用总的回文串对数减去不相交的就是答案。
我们知道利用回文树可以求出以i为结尾的回文串个数,那么以i为开始的,只需要将字符串倒着插入就好了。
另外,这道题目的字符串的长度有2百万,回文树中的next[][]数组,将会内存超限,所以只能用邻接表代替矩阵了
为了对回文树更好的学习,在求所有回文子串和的时候我们可以用两种方式,具体看代码
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include <stdio.h> using namespace std;
typedef long long int LL;
const int MAX=2*1e6;
const int mod=51123987;
int n;
char str[MAX+5];
int sum[MAX+5];
struct link //next的邻接表
{
int u[MAX+5];int v[MAX+5];
int next[MAX+5];int head[MAX+5];
int tot;
void clear()
{
memset(head,-1,sizeof(head));
tot=0;
}
void clear(int x){head[x]=-1;}
int get(int x,int y)
{
for(int i=head[x];i!=-1;i=next[i])
{
if(u[i]==y)
return v[i];
}
return 0;
}
void insert(int x,int y,int z)
{
u[tot]=y; v[tot]=z;
next[tot]=head[x];
head[x]=tot++;
} };
struct Tree
{
//int next[MAX+5][26];
int fail[MAX+5];//指向当前节点回文串中最长的后缀回文子串
int cnt[MAX+5];//当前节点的回文串一共有多少个
int num[MAX+5];//当前节点为结尾的回文子串的个数
int len[MAX+5];//当前节点的回文串的长度
int s[MAX+5];//字符串
int last;//回文树最后一个节点
int n;
int p;//回文树当前有多少个节点
link next;//邻接表,表示当前节点回文串在两端添加一个字符形成的另一个节点的回文串
int new_node(int x)
{
//memset(next[p],0,sizeof(next[p]));
cnt[p]=0;
next.clear(p);
num[p]=0;
len[p]=x;
return p++;
} void init()
{
next.clear();
p=0;
new_node(0);
new_node(-1);
last=0;
n=0;
s[0]=-1;
fail[0]=1;
} int get_fail(int x)
{
while(s[n-len[x]-1]!=s[n])
x=fail[x];
return x;
} int add(int x)
{
x-='a';
s[++n]=x;
int cur=get_fail(last);
if(!(last=next.get(cur,x)))
{
int now=new_node(len[cur]+2);
fail[now]=next.get(get_fail(fail[cur]),x);
next.insert(cur,x,now);
num[now]=num[fail[now]]+1;
last=now;
}
cnt[last]++;
return num[last];
}
LL Allsum()//求出所有回文子串的数目
{
LL ret=0; for(int i=p-1;i>0;i--)
{
cnt[fail[i]]=(cnt[fail[i]]+cnt[i])%mod; ret=(ret+cnt[i])%mod;
}
return ret;
}
}tree;
int main()
{
scanf("%d",&n);
scanf("%s",str);
tree.init();
sum[n]=0;
for(int i=n-1;i>=0;i--)
sum[i]=(sum[i+1]+tree.add(str[i]))%mod;
tree.init();
LL ans=0;LL res=0;LL res2=0;
for(int i=0;i<=n-1;i++)
{
ans=(ans+(LL)tree.add(str[i])*sum[i+1])%mod;
res2+=tree.num[tree.last];//同样也可以求所有回文子串的数目
}
res=tree.Allsum();
//cout<<res<<" "<<res2<<endl;两个是相等的
ans=(((LL)res*(res-1)/2%mod-ans)%mod+mod)%mod;
printf("%lld\n",ans);
return 0;
}
CodeForces 17E Palisection(回文树)的更多相关文章
- Palisection(Codeforces Beta Round #17E+回文树)
题目链接 传送门 题意 给你一个串串,问你有多少对回文串相交. 思路 由于正着做不太好算答案,那么我们考虑用总的回文对数减去不相交的回文对数. 而不相交的回文对数可以通过计算以\(i\)为右端点的回文 ...
- 【CF17E】Palisection(回文树)
[CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...
- Codeforces 932G Palindrome Partition - 回文树 - 动态规划
题目传送门 通往???的传送点 通往神秘地带的传送点 通往未知地带的传送点 题目大意 给定一个串$s$,要求将$s$划分为$t_{1}t_{2}\cdots t_{k}$,其中$2\mid k$,且$ ...
- CF17E Palisection(manacher/回文树)
CF17E Palisection(manacher/回文树) Luogu 题解时间 直接正难则反改成求不相交的对数. manacher求出半径之后就可以差分搞出以某个位置为开头/结尾的回文串个数. ...
- Codeforces.GYM100548G.The Problem to Slow Down You(回文树)
题目链接 \(Description\) 给定两个串\(S,T\),求两个串有多少对相同回文子串. \(|S|,|T|\leq 2\times 10^5\). \(Solution\) 好菜啊QAQ ...
- CF17E Palisection(回文树)
题意翻译 给定一个长度为n的小写字母串.问你有多少对相交的回文子 串(包含也算相交) . 输入格式 第一行是字符串长度n(1<=n<=2*10^6),第二行字符串 输出格式 相交的回文子串 ...
- Palindrome Partition CodeForces - 932G 回文树+DP+(回文后缀的等差性质)
题意: 给出一个长度为偶数的字符串S,要求把S分成k部分,其中k为任意偶数,设为a[1..k],且满足对于任意的i,有a[i]=a[k-i+1].问划分的方案数. n<=1000000 题解: ...
- 回文树练习 Part1
URAL - 1960 Palindromes and Super Abilities 回文树水题,每次插入时统计数量即可. #include<bits/stdc++.h> using ...
- 回文树 Palindromic Tree
回文树 Palindromic Tree 嗯..回文树是个什么东西呢. 回文树(或者说是回文自动机)每个节点代表一个本质不同的回文串. 首先它类似字典树,每个节点有SIGMA个儿子,表示对应的字母. ...
随机推荐
- unity, remove a scene from build settings
把scene添加到build settings的scenes in build列表里以后,如果想删除,没有菜单可用,但选中按delete即可. 参考:http://answers.unity3d.co ...
- 自定义闹钟 Reminder
Reminder reminder = ScheduledActionService.Find("MY REMINDER") as Reminder; if ( reminder ...
- java强行删除文件(针对进程正在使用的文件的删除)
boolean result = f.delete(); if(!result) { System.gc(); f.delete; }
- [原创]OpenERP 7.0 打印PDF报表 中文 乱码问题的解决方案。
网上的解决方案基本上以替换字体和安装上海先锋科技开发的软件包配置两种方案,替换字体的方案尝试了几次都么有成功,安装软件包的方案成功. 软件环境:Ubuntu Server 12.04 第一步:先到ht ...
- JVM Specification 9th Edition (4) Chapter 3. Compiling for the Java Virtual Machine
Chapter 3. Compiling for the Java Virtual Machine 内容列表 3.1. Format of Examples 3.2. Use of Constants ...
- HDFS的HA机制
传统的HDFS机制如下图所示: 也就是存在一个NameNode,一个SecondaryNameNode,然后若干个DataNode.这样的机制虽然元数据的可靠性得到了保证(靠edits,fsimage ...
- 【Mac命令行学习】(持续更新)
常用命令: 一.修改环境变量文件: 1.进入文件:vi .bash_profile 2.键盘点击[a]键,进入文件编辑 3.修改完成后,如果是vi,点击[esc]键退出编辑模式 4.输入以下命令进行具 ...
- .net 编译原理
这听起来像是个非常高大上的名字,上学的时候我们学过的编译原理或者编译技术实际上是在讲如何将高级程序语言如C++编译为计算机可以理解的汇编语言,这里说的编译原理只是想说明在.NET的世界里编译这件事儿和 ...
- 第二百三十九节,Bootstrap路径分页标签和徽章组件
Bootstrap路径分页标签和徽章组件 学习要点: 1.路径组件 2.分页组件 3.标签组件 4.徽章组件 本节课我们主要学习一下 Bootstrap 的四个组件功能:路径组件.分页组件.标签组件 ...
- windows下解决mysql忘记password
windows下解决mysql忘记password mysql有时候忘记password了怎么办?我给出案例和说明!一下就攻克了! Windows下的实际操作例如以下 1.关闭正在执行 ...