牛客多校第四场 I string 后缀自动机/回文自动机
这个回文自动机的板有问题,它虽然能过这道题,但是在计算size的时候会出锅!
题意:
求一个字符串中本质不同的连续子串有几个,但是某串和它反转后的字符串算一个。
题解:
要注意的是,一般字符串题中的“反转”,往往和回文串挂钩,反之亦然。
赛时最后半小时码的这道题,和队友很快发现了可以把字符串构造成s\$rev(s)这种形式。在这个串上求出本质不同的连续字串,这样正的和反的就都统计了一遍,再去掉带\$的连续子串,共len*(len+2)+1个,再除2就得出了结果。
但是我们忘了,即便这样反转了一次,回文串也只统计了一次。因此还要加上回文串的数量再除以二。
用后缀自动机求本质不同字符串数量,用回文自动机求本质不同回文串数量。
#include<iostream>
#include<cstring>
#include<cassert>
#define MAXN 400010
#define LL long long
using namespace std; char* strrev(char* str){
const int l = strlen(str);
for(int i=,j=l-;i<j;i++,j--){
swap(str[i],str[j]);
}
return str;
}
char s[MAXN];
char ss[MAXN];
int len; struct SAMNODE{
int ch[];
int len,fa;
SAMNODE(){memset(ch,,sizeof(ch));len=;}
}SAMdian[MAXN<<]; int SAMlas=,SAMtot=; void SAMadd(int c){
int p=SAMlas;int np=SAMlas=++SAMtot;
SAMdian[np].len=SAMdian[p].len+;
for(;p&&!SAMdian[p].ch[c];p=SAMdian[p].fa)SAMdian[p].ch[c]=np;
if(!p)SAMdian[np].fa=;//以上为case 1
else
{
int q=SAMdian[p].ch[c];
if(SAMdian[q].len==SAMdian[p].len+)SAMdian[np].fa=q;//以上为case 2
else
{
int nq=++SAMtot;SAMdian[nq]=SAMdian[q];
SAMdian[nq].len=SAMdian[p].len+;
SAMdian[q].fa=SAMdian[np].fa=nq;
for(;p&&SAMdian[p].ch[c]==q;p=SAMdian[p].fa)SAMdian[p].ch[c]=nq;//以上为case 3
}
}
} struct PTnode{
int len,fail,son[],siz;
PTnode(){
len=fail=;
for(int i=;i<=;i++)
son[i]=;
}
}PTdian[MAXN<<]; int PTlast,PTnum; int PTgetfail(int i,int x){
while(s[i-PTdian[x].len-]!=s[i]) {
x=PTdian[x].fail;
}
return x;
} void PTextend(int i,int x){
int cur=PTgetfail(i,PTlast);
if(!PTdian[cur].son[x]){
int now=++PTnum;
PTdian[now].len=PTdian[cur].len+;
PTdian[now].fail=PTdian[PTgetfail(i,PTdian[cur].fail)].son[x];
PTdian[cur].son[x]=now;
}
PTdian[PTdian[cur].son[x]].siz++;
PTlast=PTdian[cur].son[x];
} int main(){
scanf("%s",s);
len=strlen(s); PTlast=PTnum=;
PTdian[].len=-;
PTdian[].fail=PTdian[].fail=; for(int i=;i<len;i++){
PTextend(i,s[i]-'a');
} sprintf(ss,"%s%c",s,'z'+);
strrev(s);
// printf("%s\n",s);
// printf("%s\n",ss);
sprintf(ss+strlen(ss),"%s\0",s);
int len1=strlen(ss);
// printf("%s\n",ss); for(int i=;i<len1;i++){
SAMadd(ss[i]-'a');
} LL ans=;
for(int i=;i<=SAMtot;i++){
ans+=SAMdian[i].len-SAMdian[SAMdian[i].fa].len;
}
// printf("%d\n",ans); ans-=2LL*len++1LL*len*len;
ans+=PTnum-; assert(ans%==);
printf("%lld\n",ans/);
}
牛客多校第四场 I string 后缀自动机/回文自动机的更多相关文章
- 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数
目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- 牛客多校第四场 F Beautiful Garden
链接:https://www.nowcoder.com/acm/contest/142/F来源:牛客网 题目描述 There's a beautiful garden whose size is n ...
- 牛客多校第四场 G Maximum Mode
链接:https://www.nowcoder.com/acm/contest/142/G来源:牛客网 The mode of an integer sequence is the value tha ...
- 2019牛客多校第四场 A meeting
链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...
- 2019年牛客多校第四场 B题xor(线段树+线性基交)
题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...
- 牛客多校第四场 A Ternary String
题目描述 A ternary string is a sequence of digits, where each digit is either 0, 1, or 2. Chiaki has a t ...
- 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)
题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...
- 2018牛客多校第四场 J.Hash Function
题意: 给出一个已知的哈希表.求字典序最小的插入序列,哈希表不合法则输出-1. 题解: 对于哈希表的每一个不为-1的数,假如他的位置是t,令s = a[t]%n.则这个数可以被插入当且仅当第s ~ t ...
随机推荐
- python redis 批量设置过期key
在使用 Redis.Codis 时,我们经常需要做一些批量操作,通过连接数据库批量对 key 进行操作: 关于未过期: 1.常有大批量的key未设置过期,导致内存一直暴增 2.rd需求 扫描出这些ke ...
- where I will go
为什么我选择了java? 作为一个0基础入门的编程小白,大一的时候我接触了C语言,写了我的第一个程序hello world,内心有点小骄傲(我也能编程了),那时候还不知道java是什么,然而实际公司的 ...
- 通过statCounter计算给定的RDD[Double]的统计信息的方法
需求1:给定一个RDD[Double],进行计算,该RDD的统计信息(count,mean,stdev,max,min) 代码: def main(args: Array[String]): Unit ...
- 安装和使用pyspider框架时遇到的问题
安装pyspider, 直接cmd中输入 pip install pyspider, 而后提示报错 从网上找到解决方法,pycurl需要根据python版本采用wheel方法安装. 下载链接为http ...
- thinkphp 表单合法性检测
在处理表单提交的数据的时候,建议尽量采用Think\Model类提供的create方法首先进行数据创建,然后再写入数据库. 大理石平台厂家 create方法在创建数据的同时,可以进行更为安全的处理操作 ...
- PHP ftp_rmdir() 函数
定义和用法 The ftp_rmdir() 函数删除 FTP 服务器上的一个目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 ftp_rmdir(ftp_connectio ...
- 依赖背包变形——poj1947(经典)
/*这题显然不适用依赖背包的优化,因为不能保证根是必选的,但是可以按照常规依赖背包的思路进行转移,即每次对一个儿子进行C^2的转移 还是树形的背包,dp[u][j]表示u的子树里,切割出一个大小为j的 ...
- Framework7-Vue搭建项目
在Framework7的gitHub上有一套与Vue结合的模板,直接下载下来使用即可 https://github.com/framework7io/framework7-template-vue-w ...
- NX二次开发-UFUN求两个对象最短距离UF_MODL_ask_minimum_dist
NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_ui.h> UF_initialize() ...
- (转)RSA加密解密及数字签名Java实现
转:http://my.oschina.net/jiangli0502/blog/171263?fromerr=hc4izFe2 RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rives ...