国际惯例的题面:
有人说这是回文自动机的板子题,然而我是不会这种东西的。
于是,我选择用更一般性的方法去解决这个题,就是那一堆东西了。
首先,我们把两个串同时插入一个广义SAM里,拓扑排序维护每个节点的parent树的子树中来自两个串的right集合的大小sizA和sizB。
同时倍增求出parent树上每个节点向上2^k层的父亲是哪个节点。
显然一个串本质不同的回文串数量是O(n)的(什么你不知道?manacher的复杂度怎么证的?),我们对A串做manacher,在暴力拓展的时候,去后缀自动机上倍增查询这个包含这个串的最浅的节点(显然这个节点的right集合最大),这个串对答案的贡献就是这个节点的sizA*sizB了。
为了防止同样的串被统计多次,我们需要哈希和unordered_set去重。
这个题的广义SAM在建立的时候,无论如何要新建节点,不能走已有的节点,否则会导致一些节点的len变小,出现一些不合法的情况。
总体时间复杂度O(nlogn),由于这种做法常数较大,所以BZOJ光荣垫底(然而AC这题还是绰绰有余的)。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<tr1/unordered_set>
#define debug cout
typedef long long int lli;
typedef unsigned long long int ulli;
using namespace std;
using namespace tr1;
const int maxn=5e4+1e2,maxl=;
const ulli base = ; char a[maxn],b[maxn];
int la,lb;
int rec[maxn];
lli ans; struct ExtendedSuffixAutomatic {
int ch[maxn<<][],len[maxn<<],fa[maxn<<],anc[maxn<<][maxl];
int siz[maxn<<][],deg[maxn<<],root,cnt;
inline int NewNode(int ll) {
return len[++cnt] = ll , cnt;
}
ExtendedSuffixAutomatic() { root = NewNode(); }
inline void extend(int x,int p) {
int np = NewNode(len[p]+);
while( p && !ch[p][x] ) ch[p][x] = np , p = fa[p];
if( !p ) fa[np] = root;
else {
int q = ch[p][x];
if( len[q] == len[p] + ) fa[np] = q;
else {
int nq = NewNode(len[p]+);
memcpy(ch[nq],ch[q],sizeof(ch[q])) , fa[nq] = fa[q];
fa[np] = fa[q] = nq;
while( p && ch[p][x] == q ) ch[p][x] = nq , p = fa[p];
}
}
}
inline void Ex_extend(char* s,int li,int bel) {
int cur = root;
for(int i=;i<=li;i++) {
extend(s[i]-'A',cur) , cur = ch[cur][(int)s[i]-'A']; // a's A is different with b's A .
++siz[cur][bel];
if( !bel ) rec[i] = cur;
}
}
inline void topo() {
for(int i=;i<=cnt;i++) if( fa[i] ) ++deg[fa[i]];
queue<int> q;
for(int i=;i<=cnt;i++) if( !deg[i] ) q.push(i);
while( q.size() ) {
const int pos = q.front(); q.pop();
if( pos == root ) break;
anc[pos][] = fa[pos];
for(int i=;i<;i++) siz[fa[pos]][i] += siz[pos][i];
if( !--deg[fa[pos]] ) q.push(fa[pos]);
}
for(int j=;j<;j++) for(int i=;i<=cnt;i++) anc[i][j] = anc[anc[i][j-]][j-];
}
inline lli query(int pos,int lim) {
for(int j=;~j;j--) if( len[anc[pos][j]] >= lim ) pos = anc[pos][j];
return (lli) siz[pos][] * siz[pos][];
}
}esam; struct Hash {
ulli pows[maxn],h[maxn];
inline void build(char* s,int li) {
*pows = ;
for(int i=;i<=li;i++) pows[i] = pows[i-] * base , h[i] = h[i-] * base + s[i] - 'A' + ;
}
inline ulli query(int l,int r) {
return h[r] - h[l-] * pows[r-l+];
}
}hsh; unordered_set<ulli> vis; inline void calc(int al,int ar) {
ulli h = hsh.query(al,ar);
if( vis.find(h) != vis.end() ) return;
vis.insert(h) , ans += esam.query(rec[ar],ar-al+);
} inline void manacher(char* s,int li) {
static char in[maxn<<];
static int f[maxn<<],app[maxn<<],len,pos,mxr;
#define getpos_l(i) (app[i]|app[i+1])
#define getpos_r(i) (app[i]|app[i-1])
*in = '$';
for(int i=;i<=li;i++) in[++len] = s[i] , app[len] = i , in[++len] = '#';
for(int i=;i<=len;i++) {
if( i < mxr ) f[i] = min( f[pos*-i] , mxr - i );
else f[i] = ;
if( i & ) calc(getpos_l(i-f[i]+),getpos_r(i+f[i]-));
while( in[i-f[i]] == in[i+f[i]] ) {
++f[i];
calc(getpos_l(i-f[i]+),getpos_r(i+f[i]-));
}
if( i + f[i] > mxr ) mxr = i + f[i] , pos = i;
}
#undef getpos_l
#undef getpos_r
} int main() {
scanf("%s%s",a+,b+) , la = strlen(a+) , lb = strlen(b+);
esam.Ex_extend(a,la,) , esam.Ex_extend(b,lb,) , esam.topo() , hsh.build(a,la);
manacher(a,la) , printf("%lld\n",ans);
return ;
}
この校舎がつくる影
教学楼所组成的影子
待ち合わせした音楽室
在音乐教室中等候
屋上から見えた 流れてくひこうき雲
从屋顶上看到的划过天际的飞行云
まだ残ってる落書き
还残留着的涂鸦
この瞳に映るすべて
映入眼帘的一切
伝えたい ひとつひとつに
想要传达 一个一个
想い出溢れること
满溢的思念
部室の窓から探してた
从活动室窗户寻找
遠くても君なら すぐにみつけられる
即使多么遥远你也立刻找出
Bzoj4480: [Jsoi2013]快乐的jyy 广义后缀自动机 倍增 哈希 manacher的更多相关文章
-
【CF666E】Forensic Examination 广义后缀自动机+倍增+线段树合并
[CF666E]Forensic Examination 题意:给你一个字符串s和一个字符串集合$\{t_i\}$.有q个询问,每次给出$l,r,p_l,p_r$,问$s[p_l,p_r]$在$t_l ...
-
bzoj4480: [Jsoi2013]快乐的jyy
[问题描述] 给定两个字符串A和B,表示JYY的两个朋友的名字.我们用A(i,j)表示A 字符串中从第i个字母到第j个字母所组成的子串.同样的,我们也可以定义B(x,y). JYY发现两个朋友关系的紧 ...
-
[JSOI2013] 快乐的 JYY - 回文自动机,DFS
#include <bits/stdc++.h> #define Sigma 30 #define MAXN 500010 #define int long long using name ...
-
BZOJ 2894: 世界线 广义后缀自动机
Code: #include<bits/stdc++.h> #define maxn 300000 #define ll long long using namespace std; ve ...
-
bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 对[广义后缀自动机]的一些理解
先说一下对后缀自动机的理解,主要是对构造过程的理解. 构造中,我们已经得到了前L个字符的后缀自动机,现在我们要得到L+1个字符的后缀自动机,什么需要改变呢? 首先,子串$[0,L+1)$对应的状态不存 ...
-
BZOJ 3926 &;&; ZJOI 2015 诸神眷顾的幻想乡 (广义后缀自动机)
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MB Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽 ...
-
BZOJ 3277 串 (广义后缀自动机)
3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...
-
BZOJ 3473: 字符串 [广义后缀自动机]
3473: 字符串 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 354 Solved: 160[Submit][Status][Discuss] ...
-
BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)
题目链接 \(Description\) 给定n个模式串,多次询问一个串在多少个模式串中出现过.(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点,我们需要得 ...
随机推荐
-
Net作业调度(二) -CrystalQuartz远程管理
Source Code-1.6M 介绍 上篇已经了解Quartz.NET的基本使用方法了.但如果想方便的知道某个作业执行情况,需要暂停,启动等操作行为,这时候就需要个Job管理的界面. 本文介绍Qua ...
-
企业级应用框架(五)IOC容器在框架中的应用
前言 在上一篇我大致的介绍了这个系列所涉及到的知识点,在本篇我打算把IOC这一块单独提取出来讲,因为IOC容器在解除框架层与层之间的耦合有着不可磨灭的作用.当然在本系列前面的三篇中我也提供了一种基于反 ...
-
Java通过axis调用WebService
上午头给了我一个任务,让我对接别的公司的webservice接口,各种百度,看的头晕脑花的,终于通了,记录一下吧. jar包奉上,http://pan.baidu.com/s/1jSchC 包含:ax ...
-
MDX笔记
为啥要写这一篇博客:之前断断续续的学习过MDX,也大致学会了基本语法,理解了基本用法,但是用的机会不多,到了真正用的时候,无从下手,十分尴尬!故此,将语法和基本用法温故总结,结合实例将MDX做个阶段性 ...
-
「OC」构造方法和分类
一.构造方法 (一)构造方法的调用 创建一个可用的对象:Person *p=[Person new]; new方法实际上是分为两步来创建一个对象: 1)使用+alloc方法来分配存储空间(返回分配的对 ...
-
java--创建多线程两种方法的比较
[通过继承Thread] 一个Thread对象只能创建一个线程,即使它调用多次的.start()也会只运行一个的线程. [看下面的代码 & 输出结果] package Test; class ...
-
时间序列分析算法【R详解】
简介 在商业应用中,时间是最重要的因素,能够提升成功率.然而绝大多数公司很难跟上时间的脚步.但是随着技术的发展,出现了很多有效的方法,能够让我们预测未来.不要担心,本文并不会讨论时间机器,讨论的都是很 ...
-
一个可以拖动的自定义Gridview代码
这个可以拖动的gridview继承于gridview,所以,用法和gridview一样, 代码如下: public class DragGridView extends GridView { priv ...
-
BZOJ_3262_陌上花开_CDQ分治+树状数组
BZOJ_3262_陌上花开_CDQ分治+树状数组 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的 ...
-
memcached性能测试之Twemperf
Twemperf又名mcperf,是一款memcached的性能测试工具.Mcperf就像httperf,但它基于memcached的协议,它使用memcached的ASCII协议并且能够快速的产生大 ...