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个儿子,表示对应的字母. ...
随机推荐
- C# 使用TASK处理多任务同时处理
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- html调用摄像头的方法汇总
1.在PC端打开摄像头的方法:(移动端不能使用) 能够实现打开摄像头并截图 <!doctype html> <html lang="en"> <hea ...
- 4~20mA模拟输出(电流环)应用笔记(转)
https://zm12.sm-tc.cn/?src=http%3A%2F%2Fwww.aichengxu.com%2Fview%2F5397788&uid=d2f68cd7fd230c162 ...
- JVM虚拟机(一):java虚拟机的基本结构
1: 类加载子系统(负责从文件系统或者网络中加载class信息,加载的类信息存放于一块成为方法区的内存空间.除了类信息外,方法区中可能还存放运行时常量池信息,包括字符串字面量和数字常量(这部分常量信息 ...
- [k8s]kubectl windows配置(kubernetic) && kubectl config set-context使用Kubernetic
参考: https://feisky.gitbooks.io/kubernetes/components/kubectl.html https://kubernetes.io/docs/tasks/t ...
- 已安装 SQL Server 2005 Express 工具。若要继续,请删除 SQL Server 2005 Express 工具
数据库安装sql server2008R2时遇到. 安装sql server 2008 management,提示错误:Sql2005SsmsExpressFacet 检查是否安装了 SQL Serv ...
- lantin1
Latin1是ISO-8859-1的别名,有些环境下写作Latin-1. ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCI ...
- mui调用webservice
document.getElementById("confirm").addEventListener('tap', function() {var respnoseEl = do ...
- UVALive 3942 Remember the Word 字典树+dp
/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...