这个回文自动机的板有问题,它虽然能过这道题,但是在计算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 后缀自动机/回文自动机的更多相关文章

  1. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  2. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  3. 牛客多校第四场 F Beautiful Garden

    链接:https://www.nowcoder.com/acm/contest/142/F来源:牛客网 题目描述 There's a beautiful garden whose size is n ...

  4. 牛客多校第四场 G Maximum Mode

    链接:https://www.nowcoder.com/acm/contest/142/G来源:牛客网 The mode of an integer sequence is the value tha ...

  5. 2019牛客多校第四场 A meeting

    链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...

  6. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  7. 牛客多校第四场 A Ternary String

    题目描述 A ternary string is a sequence of digits, where each digit is either 0, 1, or 2. Chiaki has a t ...

  8. 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)

    题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...

  9. 2018牛客多校第四场 J.Hash Function

    题意: 给出一个已知的哈希表.求字典序最小的插入序列,哈希表不合法则输出-1. 题解: 对于哈希表的每一个不为-1的数,假如他的位置是t,令s = a[t]%n.则这个数可以被插入当且仅当第s ~ t ...

随机推荐

  1. 从零开始搭建系统2.1——Nexus安装及配置

    在安装配置Nexus时,请先确定您已经配置好jdk 1.创建目录 2.下载安装包 [root@localhost usr]# cd nexus 下载地址:https://www.sonatype.co ...

  2. dev中 ,usercontrol打印界面内容,打印预览和打印

    首先,在对应的文件夹下面添加引用,如下图 如果没有就下载下来包. 预先在本地文件夹下面建立.frx文件,像这样的, 然后在触发事件下面写 //打印预览 private void btn_Preview ...

  3. php导出csv并保存在服务器,返回csv的文件路径

    <?php namespace app\common\controller; use think\Controller; use think\Db; class Csv extends Cont ...

  4. 30 System类

    System类代表系统,系统级的很多属性和控制方法都放置在该类的内部.该类位于java.lang包.由于该类的构造方法是private的,所以无法创建该类的对象,也就是无法实例化该类.其内部的成员变量 ...

  5. python 模拟按键模拟键盘按键按下放开

    python模拟按键 pip install pypiwin32安装库 import win32conimport win32apiimport time 导入 打个比方模拟A win32api.ke ...

  6. eclipse背景设置什么颜色缓解眼睛疲劳

    eclipse背景设置什么颜色缓解眼睛疲劳 1.打开window->Preference,弹出Preference面板 2.展开General标签,选中Editors选项,展开. 3.选中 Te ...

  7. android高级篇收录

    Android运行时性能优化 1.android启动优化 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」 支付宝 App 构建优化解析:通过安装包重排布优化 Android 端 ...

  8. NX二次开发-UFUN拾取屏幕位置UF_UI_specify_screen_position

    #include <uf.h> #include <uf_ui.h> UF_initialize(); //拾取屏幕位置 //在屏幕用鼠标拾取一点 char sMessage[ ...

  9. Rootkit之SSDT hook(通过CR0)

    CR0当中有一个写保护位,是保护内存不可写属性的,为了能够写入内核,只能把它的保护给咔嚓掉了,不过--如果做完了手脚但不还原写保护属性的话,极有可能会BOSD. /================== ...

  10. 关于group by的用法

    重新回顾并理解group by. 首先设计一张表,表名为test 然后执行以下SQL语句: select name from test group by name 获得执行结果: 可是为了能够更好的理 ...