应该算是远古时期的一道题了吧,不过感觉挺经典的。

题意是给出三一个字符串s,a,b,求以a开头b结尾的本质不同的字符串数。

由于n不算大,用hash就可以搞,不过这道题是存在复杂度$O(nlogn)$的做法的。

由于要求本质不同,所以可以考虑使用后缀数组来不重复地枚举字符串。

首先用两个不同的其他字符将s,a,b拼起来求后缀数组,这样就可以知道任意两个后缀的lcp了。然后将s中所有b出现的末尾位置置1,求个后缀和suf。将s中所有后缀按名次从小到大存到一个vector里。对于s中的每个后缀,设其名次为x,a的长度为la,b的长度为lb,若$lcp(x,rnk[ia])=la$,则其对答案的贡献为$suf[sa[i]+max(lcp(x,vec[i-1]),la-1,lb-1)]$。其中la-1和lb-1是为了保证字符串长度比a和b都大,lcp(x,vec[i-1])是为了保证不重复枚举,相当于没有将s与a,b拼起来时的height[x]。特别地,当x=0时为0。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+;
char buf[N];
int s[N],sa[N],buf1[N],buf2[N],c[N],n,rnk[N],ht[N],ST[N][],Log[N],ia,ib,m,la,lb,suf[N];
void Sort(int* x,int* y,int m) {
for(int i=; i<m; ++i)c[i]=;
for(int i=; i<n; ++i)++c[x[i]];
for(int i=; i<m; ++i)c[i]+=c[i-];
for(int i=n-; i>=; --i)sa[--c[x[y[i]]]]=y[i];
}
void da(int* s,int n,int m=) {
int *x=buf1,*y=buf2;
s[n]=x[n]=y[n]=-;
for(int i=; i<n; ++i)x[i]=s[i],y[i]=i;
Sort(x,y,m);
for(int k=; k<n; k<<=) {
int p=;
for(int i=n-k; i<n; ++i)y[p++]=i;
for(int i=; i<n; ++i)if(sa[i]>=k)y[p++]=sa[i]-k;
Sort(x,y,m),p=,y[sa[]]=;
for(int i=; i<n; ++i)y[sa[i]]=x[sa[i-]]==x[sa[i]]&&x[sa[i-]+k]==x[sa[i]+k]?p-:p++;
if(p==n)break;
swap(x,y),m=p;
}
}
void getht() {
for(int i=; i<n; ++i)rnk[sa[i]]=i;
ht[]=;
for(int i=,k=; i<n; ++i) {
if(k)--k;
if(!rnk[i])continue;
for(; s[i+k]==s[sa[rnk[i]-]+k]; ++k);
ht[rnk[i]]=k;
}
}
void initST() {
for(int i=; i<n; ++i)ST[i][]=ht[i];
for(int j=; (<<j)<=n; ++j)
for(int i=; i+(<<j)-<n; ++i)
ST[i][j]=min(ST[i][j-],ST[i+(<<(j-))][j-]);
}
int lcp(int l,int r) {
if(l==r)return n-sa[l];
if(l>r)swap(l,r);
l++;
int k=Log[r-l+];
return min(ST[l][k],ST[r-(<<k)+][k]);
}
vector<int> vec;
int main() {
Log[]=-;
for(int i=; i<N; ++i)Log[i]=Log[i>>]+;
scanf("%s",buf),m=strlen(buf);
for(int i=; i<m; ++i)s[n++]=buf[i];
s[n++]='z'+,ia=n;
scanf("%s",buf),m=strlen(buf),la=m;
for(int i=; i<m; ++i)s[n++]=buf[i];
s[n++]='z'+,ib=n;
scanf("%s",buf),m=strlen(buf),lb=m;
for(int i=; i<m; ++i)s[n++]=buf[i];
s[n]=;
da(s,n),getht(),initST();
for(int i=; i<ia-; ++i)if(lcp(rnk[i],rnk[ib])==lb)suf[i+lb-]=;
for(int i=ia-; i>=; --i)suf[i]+=suf[i+];
for(int i=; i<ia-; ++i)vec.push_back(rnk[i]);
sort(vec.begin(),vec.end());
int ans=;
for(int i=; i<vec.size(); ++i) {
int x=vec[i];
if(lcp(x,rnk[ia])==la)ans+=suf[sa[x]+max(i?lcp(x,vec[i-]):,max(la-,lb-))];
}
printf("%d\n",ans);
return ;
}

CodeForces - 113B Petr# (后缀数组)的更多相关文章

  1. Liar CodeForces - 822E (dp,后缀数组)

    大意: 给定串$s,t$, 给定整数$x$, 求判断$t$是否能划分为至多$x$段, 使这些段在$s$中按顺序,不交叉的出现. 设$dp_{i,j}$表示$s$匹配到$i$位, 划分了$j$段, 匹配 ...

  2. CodeForces 113B Petr#

    题目链接:http://codeforces.com/problemset/problem/113/B 题目大意: 多组数据每组给定3个字符串T,Sbeg,Sed,求字符串T中有多少子串是以Sbeg开 ...

  3. Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp

    D. New Year and Ancient Prophecy 题目连接: http://www.codeforces.com/contest/611/problem/C Description L ...

  4. 【Codeforces 113B】Petr#

    Codeforces 113 B 题意:有一个母串\(S\)以及两个串\(S_{begin}\)和\(S_{end}\),问\(S\)中以\(S_{begin}\)为开头并且以\(S_{end}\)为 ...

  5. Codeforces 432D Prefixes and Suffixes (KMP、后缀数组)

    题目链接: https://codeforces.com/contest/432/problem/D 题解: 做法一: KMP 显然next树上\(n\)的所有祖先都是答案,出现次数为next树子树大 ...

  6. Codeforces 1063F - String Journey(后缀数组+线段树+dp)

    Codeforces 题面传送门 & 洛谷题面传送门 神仙题,做了我整整 2.5h,写篇题解纪念下逝去的中午 后排膜拜 1 年前就独立切掉此题的 ymx,我在 2021 年的第 5270 个小 ...

  7. Codeforces Round #246 (Div. 2) D. Prefixes and Suffixes(后缀数组orKMP)

    D. Prefixes and Suffixes time limit per test 1 second memory limit per test 256 megabytes input stan ...

  8. Codeforces #123D: 后缀数组+单调栈

    D. String     You are given a string s. Each pair of numbers l and r that fulfill the condition 1 ≤  ...

  9. Codeforces VK Cup 2015 A.And Yet Another Bracket Sequence(后缀数组+平衡树+字符串)

    这题做得比较复杂..应该有更好的做法 题目大意: 有一个括号序列,可以对其进行两种操作: ·        向里面加一个括号,可以在开头,在结尾,在两个括号之间加. ·        对当前括号序列进 ...

随机推荐

  1. NDK学习笔记-多线程与生产消费模式

    在做NDK开发的时候,很多情况下都是需要使用多线程的,一方面是提高程序运行效率,另一方面就是防止主线程阻塞 C的多线程 在C语言里,可以通过对于POSIX标准的运用,使得C语言执行多线程 提高程序的执 ...

  2. Vue CLI 3 如何自定义 js 的文件名

    参考链接:https://blog.csdn.net/weixin_33979363/article/details/88742342

  3. 文件input框选择图片实时显示小技巧

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Reactor系列(九)collect集合

    #java#reactor#collect#collectMap#collectList# 集合 视频讲解: https://www.bilibili.com/video/av79860614/ Fl ...

  5. nginx源码安装(CentOS版)

    准备工作: 1) 配好网易yum源 登录此网站(http://mirrors.163.com/.help/centos.html),下载相应版本的yum源至服务器的/etc/yum.repos.d/目 ...

  6. centos7服务搭建常用服务配置之一:SSH

    目录 1 SSH服务协议 1.1 ssh服务协议说明 1.2 ssh服务工作机制 1.3 ssh加密技术说明 1.3.1 ssh实现安全链接建立,利用要是和锁头 1.3.2 ssh加密算法 1.4 s ...

  7. ajax提交 的编码小结

    今天用ajax的post方法提交数据给webservice,由于有email的缘故发现,注册方法调用总是报错,打开报文一看提交的 发现@符号被变成了%40 , abc@126.com 即abc%401 ...

  8. (十六)JDBC 处理大数据

    目录 前言: 基本概念 对于Mysql的Text类型 流地址的写法 blob类型数据 备注 前言: 在实际开发中,程序需要把 大文本或二进制 数据保存到数据库中: 实际上,我们并不存储大的数据到数据库 ...

  9. vscode+php+xdebug won't stop at breakpoint 断点不起作用

    not stopping on breakpoints breakpoint not working 原因: 1) php.ini xdebug 端口不配置的情况下,默认是 9000,如果vscode ...

  10. Job和Service

    Job及CronJob: ---apiVersion: batch/v1kind: Jobmetadata:  name: job-demospec:  template:    metadata:  ...