2019牛客全国多校训练四 I题 string (SAM+PAM)
链接:https://ac.nowcoder.com/acm/contest/884/I
来源:牛客网
题目描述
输入描述:
A line containing a string sss of lower-case letters.
输出描述:
A positive integer - the largest possible number of substrings of sss that are non-equivalent.
输入
abac
输出
8
说明
The set of following substrings is such a choice: abac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,c.
备注:
1≤∣s∣≤2×1051 \leq |s|\leq 2 \times 10^51≤∣s∣≤2×105, sss is consisted of lower-case letters.
题解:
题目给你一个字符串s,让你求s中的子串组成的最大集合,满足这个集合内的每一个子串str, str和rev(str)不同时存在{rev(str):表示str反过来}
思路:就是先用SAM统计出s#rev(s)中不包含 '#'的所有子串ans1; 然后用PAM统计出s中本质不同的子串数量ans2;
这答案就是(ans1+ans2)/2;
为什么呢?
因为在用SAM统计s#rev(s)的时候会把所有字符串统计两边,而本身就是回文串的只会统计一遍。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
#define pil pair<int,long long>
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3fll;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int maxn=4e5+;
const int MAXN=4e5+;
char str[maxn];
int s[maxn];
ll ans;
struct SAM{
int l[maxn<<],fa[maxn<<],nxt[maxn<<][];
int last,cnt; void Init()
{
ans=;last=cnt=;
l[cnt]=fa[cnt]=;
memset(nxt[cnt],,sizeof(nxt[cnt]));
} int NewNode()
{
++cnt;
memset(nxt[cnt],,sizeof(nxt[cnt]));
l[cnt]=fa[cnt]=;
return cnt;
} void Insert(int ch)
{
int np=NewNode(),p=last;
last=np; l[np]=l[p]+;
while(p&&!nxt[p][ch]) nxt[p][ch]=np,p=fa[p];
if(!p) fa[np]=;
else
{
int q=nxt[p][ch];
if(l[p]+==l[q]) fa[np]=q;
else
{
int nq=NewNode();
memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
fa[nq]=fa[q];
l[nq]=l[p]+;
fa[np]=fa[q]=nq;
while(nxt[p][ch]==q) nxt[p][ch]=nq,p=fa[p];
}
}
ans+=1ll*(l[last]-l[fa[last]]);
} }sam; struct Palindromic_Tree{
int next[MAXN][];
int fail[MAXN];
int cnt[MAXN];
int num[MAXN];
int len[MAXN];
int S[MAXN];
int last;
int n;
int p; int newnode(int l)
{
for(int i=;i<;++i) next[p][i]=;
cnt[p]=;
num[p]=;
len[p]=l;
return p++;
} void Init()
{
p=;
newnode( );
newnode(-);
last=;
n=;
S[n]=-;
fail[]=;
} int get_fail(int x)
{
while(S[n-len[x]-]!=S[n])x=fail[x] ;
return x ;
} void add(int c)
{
S[++ n]=c;
int cur=get_fail(last) ;
if(!next[cur][c])
{
int now=newnode(len[cur]+) ;
fail[now]=next[get_fail(fail[cur])][c] ;
next[cur][c]=now ;
num[now]=num[fail[now]]+;
}
last=next[cur][c];
cnt[last]++;
} ll count()
{
ll res=p*1ll;
for(int i=p-;i>=;--i) cnt[fail[i]]+=cnt[i];
//for(int i=1;i<=p;++i) res+=cnt[i];
//cout<<"res "<<res<<endl;
return (res-);
}
} pam; int main()
{
scanf("%s",str);
int len=strlen(str); sam.Init();
for(int i=;i<len;++i) sam.Insert(str[i]-'a');
sam.Insert();
for(int i=len-;i>=;--i) sam.Insert(str[i]-'a');
ans-=1ll*(len+)*(len+);
//cout<<"ans "<<ans<<endl;
pam.Init();
for(int i=;i<len;++i) pam.add(str[i]-'a');
ans=ans+pam.count(); printf("%lld\n",(ans/2ll)); return ;
}
2019牛客全国多校训练四 I题 string (SAM+PAM)的更多相关文章
- 2019牛客全国多校第八场A题 All-one Matrices(单调栈)
题意:让你找最大不可扩展全1子矩阵的数量: 题解:考虑枚举每一行为全1子矩阵的的底,然后从左到右枚举:up[i][j]:表示(i,j)这个位置向上可扩展多少,同时还有记录每个位置(i,j)向左最多可扩 ...
- 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)
layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 牛客网多校训练第二场D Kth Minimum Clique
链接:https://ac.nowcoder.com/acm/contest/882/D来源:牛客网 Given a vertex-weighted graph with N vertices, fi ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第八场)E.Explorer
链接:https://ac.nowcoder.com/acm/contest/888/E来源:牛客网 Gromah and LZR have entered the fifth level. Unli ...
随机推荐
- 深入理解计算机系统 第八章 异常控制流 part2
关于进程,需要关注其提供给应用程序的两个关键抽象: 1.一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占地使用处理器 2.一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用内存系统 ...
- 《计算机网络 自顶向下方法》 第6章 链路层和局域网 Part2
待补充完善 Web 页面的请求历程 应用层 报文.主机 运输层 报文段. 网络层 数据报.路由器.IP 地址 链路层 以太网帧.交换机.MAC 地址 步骤 1)到 4) ...
- 大学生活这样过,校招 offer 飞来找
01.开门见山 由于我比较喜欢分享的原因,认识了不少大学生.其中有不少佼佼者,比如说一年读 50 本书的璐璐,校招斩获一线大厂 Offer 的晓峰,通过运营公众号实现经济独立的帅土. 当然也有一些不知 ...
- RabbitMQ 的高可用集群
RabbitMQ 的高可用性 RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用的 RabbitMQ 有三种模式:单机模式.普通集群模式.镜像集群模式. 单机模式 单机模式,生产几 ...
- Intellij IDEA搭建JSP+Tomcat开发环境
1.新建项目 然后填入项目名称和选择项目路径,填完点击完成. 2.添加WEB框架 别问我为什么不一开始就直接新建WEB框架,因为我也是看的别人的教程0.0 不过还遇到了一些新问题,后面会讲到 3.配置 ...
- spark集群搭建(三台虚拟机)——hadoop集群搭建(2)
!!!该系列使用三台虚拟机搭建一个完整的spark集群,集群环境如下: virtualBox5.2.Ubuntu14.04.securecrt7.3.6_x64英文版(连接虚拟机) jdk1.7.0. ...
- 力扣(LeetCode)二进制求和 个人题解
给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = "11", b = "1" 输出: ...
- 领扣(LeetCode)找树左下角的值 个人题解
给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 注意: 您可以假 ...
- nvidia gtx1050在kali linux系统下安装显卡驱动,且可以使用x-setting切换显卡
转自:https://www.zzhsec.com/255.html 1.更换源[使用中科大或者官方源都可以] 下面使用中科大的源 root@Andy:/home/dnt# vi /etc/apt/s ...
- Fortran输入输出与声明--xdd
1.建议程序总体格式: program ex1. ... end progr 2.想要打出 My name is "xdd". write(*,*)" My name i ...