卡空间PAM,2010没有PAM,所以都是马拉车

众所周知,PAM拥有十分优秀的时间复杂度,但空间复杂度lj得不行

但这题卡空间,所以得用到邻接链表PAM

先讲思路

题目要求相交的回文子串对,这很难做

于是我们求补集,求不相交的回文子串对,再用总数减即可

求法和上文的最长双回文子串 类似

正反建一次PAM,存该位置结尾的回文子串个数,然后加法改乘法

自己领悟一下,挺简单的。

现在讲一下邻接链表PAM

注意:邻接链表PAM不是使空间变小了,而是用时间换空间

我们记边结构体\(line\)

存\(3\)个信息:\(nx,to,w\) 分别表示上一条边,这条边通向的节点编号,这条边是代表哪个字符

数组\(fir[i]\)表示\(i\)伸出的最后一条边的编号(头插式

当我们要寻找\(u\)的\(v\)儿子

我们就像邻接链表一样找,直到有一条边的\(w==v\)为止

找不到记得指根

int getson(int u,int v){
for(int i=u;i!=-1;i=l[i].nx)
if(l[i].w==v)return l[i].to;
return -1;
}

建点的时候把边建上

void insert(int u,int i){
int Fail=getfail(pre,i),ls=getfail(fail[Fail],i);
if(getson(fir[Fail],u)==-1){
if(getson(fir[ls],u)==-1)fail[++tot]=0; //找不到指根
else fail[++tot]=getson(fir[ls],u); //找到了
l[++cnt]=(line){fir[Fail],tot,u};fir[Fail]=cnt; //加边
len[tot]=len[Fail]+2;
ans[tot]=ans[fail[tot]]+1; //结尾回文子串个数
pre=tot;
}else
pre=getson(fir[Fail],u);
}

然鹅事实上你仍然过不了,你还要继续压空间,省掉一堆数组就可以过啦!

总代码:

#include<bits/stdc++.h>
#define maxn 2000005
#define mod 51123987
using namespace std;
char s[maxn];
int slen,b[maxn];
long long res;
int fail[maxn],len[maxn],ans[maxn],fir[maxn];
struct line{int nx,to,w;}l[maxn];
int tot,pre,cnt;
void init(){
memset(fir,-1,sizeof(fir));cnt=0;
fail[0]=1;len[1]=-1;tot=1;pre=0;
}
int getfail(int x,int i){
while(i-len[x]-1<0||s[i-len[x]-1]!=s[i])x=fail[x];
return x;
}
int getson(int u,int v){
for(int i=u;i!=-1;i=l[i].nx)
if(l[i].w==v)return l[i].to;
return -1;
}
void insert(int u,int i){
int Fail=getfail(pre,i),ls=getfail(fail[Fail],i);
if(getson(fir[Fail],u)==-1){
if(getson(fir[ls],u)==-1)fail[++tot]=0;
else fail[++tot]=getson(fir[ls],u);
l[++cnt]=(line){fir[Fail],tot,u};fir[Fail]=cnt;
len[tot]=len[Fail]+2;
ans[tot]=ans[fail[tot]]+1;
pre=tot;
}else
pre=getson(fir[Fail],u);
}
int main(){
int n;
scanf("%d",&n);
scanf("%s",s);slen=strlen(s);init();
reverse(s,s+slen);
for(int i=0;i<slen;i++)insert(s[i]-'a',i),b[slen-i-1]=ans[pre];
for(int i=slen-1;i>=0;i--)b[i]+=b[i+1],b[i]%=mod;
reverse(s,s+slen);init();
for(int i=0;i<slen-1;i++){
insert(s[i]-'a',i);int x=ans[pre];
res+=(1ll*x*b[i+1])%mod,res%=mod;
}
printf("%lld\n",((1ll*b[0]*(b[0]-1)/2ll)%mod-res+mod)%mod);
return 0;
}

题解 CF17E 【Palisection】的更多相关文章

  1. CF17E Palisection(manacher/回文树)

    CF17E Palisection(manacher/回文树) Luogu 题解时间 直接正难则反改成求不相交的对数. manacher求出半径之后就可以差分搞出以某个位置为开头/结尾的回文串个数. ...

  2. CF17E Palisection——优秀的综合计数题

    题意翻译 给定一个长度为n的小写字母串.问你有多少对相交的回文子 串(包含也算相交) . 输入格式 第一行是字符串长度n(1<=n<=2*10^6),第二行字符串 输出格式 相交的回文子串 ...

  3. CF17E Palisection manacher

    题面:洛谷(带翻译) 题解: 直接求相交不太好求,所以考虑求不相交的回文串对数. 设ll[i]表示以i为开头的回文串个数,rr[i]表示结尾<=i的回文串个数. 然后不相交的回文串对数显然就是对 ...

  4. CF17E Palisection(回文自动机)

    题意翻译 给定一个长度为n的小写字母串.问你有多少对相交的回文子 串(包含也算相交) . 输入格式 第一行是字符串长度n(1<=n<=2*10^6),第二行字符串 输出格式 相交的回文子串 ...

  5. CF17E Palisection(manacher)

    题意 给出一个长度为N的字符串S,问S中有多少个回文子串对(i,j)使得i,j在S中的位置相交?(N<=2*106) 题解 #include<iostream> #include&l ...

  6. CF17E Palisection(回文树)

    题意翻译 给定一个长度为n的小写字母串.问你有多少对相交的回文子 串(包含也算相交) . 输入格式 第一行是字符串长度n(1<=n<=2*10^6),第二行字符串 输出格式 相交的回文子串 ...

  7. CF17E Palisection 差分+manacher算法

    题目大意: 给定一个串$S$,询问有多少对相交的回文子串 直接做的办法: 我们先考虑求出以$i$为结尾的串的数量,这个很好统计 之后,我们再求出所有包含了点$i$的回文串的数目 这个相当于在$i$的左 ...

  8. CF17E Palisection

    题意 给定一个长度为n的小写字母串.问你有多少对相交的回文子串(包含也算相交) 相交的回文子串个数 \(mod\ 51123987\) Sol 求相交的回文子串不太好求 考虑用总数减去不相交的回文串个 ...

  9. CF17E Palisection (回文自动机+DP)

    题目传送门 题目大意:给你一个字符串,让你求出有多少对相交的回文子串 啊啊啊啊降智了,我怎么又忘了正难则反! 求相交会很难搞.把问题转化成求互不相交的回文子串再减一下就行了 先利用$PAM$求出以每个 ...

随机推荐

  1. java file已存在,新建流写入此文件是否会覆盖原本file信息

    java中建立文件输出流,当文件不存在时会新建一个文件:如果有同名文件,自动覆盖.不存在时自动建立.FileOutputStream的默认构造方法是直接覆盖掉原来的文件,而FileOutputStre ...

  2. 剑指Offer系列_09_用两个栈实现队列

    package leetcode.sword_to_offfer.day01; import java.util.LinkedList; /** * 用两个栈实现一个队列.队列的声明如下,请实现它的两 ...

  3. 对已有的docker容器增加新的端口映射

    一般在运行容器时,我们都会通过参数 -p(使用大写的-P参数则会随机选择宿主机的一个端口进行映射)来指定宿主机和容器端口的映射,例如 docker run -it -d --name [contain ...

  4. 动静分离+url地址重定向+HTTPS协议

    动静分离+url地址重定向+HTTPS协议

  5. JAVA 对象的创建与克隆

    目录 一.对象的4种创建方式 二.通过new创建对象 三.反射 四.克隆对象 浅拷贝 深拷贝 五.反序列化 六.补充 一.对象的4种创建方式 new 创建 反射 克隆 反序列化 二.通过new创建对象 ...

  6. 如何封装安全的go

    如何封装安全的go 在业务代码开发过程中,我们会有很大概率使用go语言的goroutine来开启一个新的goroutine执行另外一段业务,或者开启多个goroutine来并行执行多个业务逻辑.所以我 ...

  7. windbg调试系列教程:sos扩展的介绍和使用

    SOS是什么? 直观来说,sos就是一个程序集文件.这个程序集的作用就是让我们在使用windbg分析.net进程时,更加方便快捷.通过sos,我们可以清晰的查看CLR运行时的各类信息,辅助我们去理解托 ...

  8. 新手菜菜之2020Kubernetes详细介绍大全

    前文 Kubernetes笔记(一):十分钟布置一套K8s环境 介绍了怎么快速建立一个k8s体系.为了持续运用k8s来布置咱们的应用,需要先对k8s中的一些根本组件与概念有个了解. Kubernete ...

  9. pytest--fixture基本使用(主要用来进行测试环境的初始化和清理,fixture中的params参数还可以用来进行参数化)

    fixture fixture修饰器来标记固定的工厂函数,在其他函数,模块,类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作. 方法: fixture(scope=" ...

  10. k8s搭建监控:安装metrics server和dashboard

      安装metrics server 参考:https://github.com/kubernetes-sigs/metrics-server kubectl  create -f component ...