●BZOJ 3796 Mushroom追妹纸
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=3796
题解:
题意:
给出三个串 A,B,C
找出一个最长串 S,
使得 S是A,B 的子串,但是 C不是S的子串。
首先,对于第一二个限制,只需要把 A,B串用一个分隔符连接在一起。
求出sa[],rank[],height[]数组,
那么在排好序的后缀中,相邻的两个后缀如果一个属于A串(令在A串p位置),另一个属于B串的话,
则可能贡献答案。 但应该贡献多少呢?
由于有 C 的限制,即在LCP中选出的最长前缀里不能出现 C串。
所以考虑如下做法。
定义 appear[i] 表示 A串的 i位置后面第一次出现 C串的开始位置。
求出这个以后,那么就可以贡献答案了:
ANS=max(ANS,min(hei[i],appear[i]-p+LenC-1))
以下是求pre数组的做法:
把 A串作为文本串,C串作为匹配串,用 KMP去匹配。
并在 A串中每一个出现 C串的开始位置打上标记
然后反向跑一边,得出appear[]数组。
总的复杂度 (Nlog2N+N)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100500
#define INF 0x3f3f3f3f
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
char S[MAXN],A[MAXN],B[MAXN],C[MAXN];
int sa[MAXN],rak[MAXN],hei[MAXN],app[MAXN];
int L1,L2,L3,ANS;
void build(int N,int M){
static int cc[MAXN],ta[MAXN],tb[MAXN],*x,*y,h,p;
x=ta; y=tb; h=0;
for(int i=0;i<M;i++) cc[i]=0;
for(int i=0;i<N;i++) cc[x[i]=S[i]]++;
for(int i=1;i<M;i++) cc[i]+=cc[i-1];
for(int i=N-1;i>=0;i--) sa[--cc[x[i]]]=i;
for(int k=1;p=0,k<N;k<<=1){
for(int i=N-k;i<N;i++) y[p++]=i;
for(int i=0;i<N;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<M;i++) cc[i]=0;
for(int i=0;i<N;i++) cc[x[y[i]]]++;
for(int i=1;i<M;i++) cc[i]+=cc[i-1];
for(int i=N-1;i>=0;i--) sa[--cc[x[y[i]]]]=y[i];
swap(x,y); y[N]=-1; x[sa[0]]=0; M=1;
for(int i=1;i<N;i++)
x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?M-1:M++;
if(M>=N) break;
}
for(int i=0;i<N;i++) rak[sa[i]]=i;
for(int i=0,j;i<N;i++){
if(h) h--;
if(rak[i]){
j=sa[rak[i]-1];
while(S[i+h]==S[j+h]) h++;
}
hei[rak[i]]=h;
}
}
void KMP(char *T,char *S){
static int nxt[MAXN],i,j,k,lT,lS;
memset(app,0x3f,sizeof(app));
nxt[0]=-1; lT=strlen(T); lS=strlen(S);
j=0; k=-1;
while(j<lS){
if(k==-1||S[j]==S[k]) j++,k++,nxt[j]=k;
else k=nxt[k];
}
i=0; j=0;
while(i<lT){
if(j==-1||T[i]==S[j]){
i++; j++;
if(!S[j]) app[i-lS]=i-lS;
}
else j=nxt[j];
}
for(int i=lT-1;i>=0;i--) app[i]=min(app[i],app[i+1]);
}
bool bel(int p){
if(p<L1) return 0;
else return 1;
}
int main()
{
int N;
scanf(" %s %s %s",A,B,C);
L1=strlen(A); L2=strlen(B); L3=strlen(C); N=L1+L2+1;
for(int i=0;i<L1;i++) S[i]=A[i]; S[L1]='&';
for(int i=0;i<L2;i++) S[L1+i+1]=B[i]; S[N]=0;
build(N,300);
KMP(A,C);
for(int i=1,p,q;i<N;i++){
if(hei[i]<=ANS||!(bel(sa[i-1])^bel(sa[i]))) continue;
if(!bel(sa[i-1])) p=sa[i-1]; else p=sa[i]; q=app[p];
ANS=max(ANS,min(hei[i],q-p+L3-1));
}
printf("%d",ANS);
return 0;
}
●BZOJ 3796 Mushroom追妹纸的更多相关文章
- [BZOJ 3796]Mushroom追妹纸
[BZOJ 3796]Mushroom追妹纸 题目 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他 ...
- bzoj 3796 Mushroom追妹纸——后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3796 长度一般都是 1e5 ,看这个是 5e4 ,一看就是把两个串接起来做. 自己本来想的是 ...
- bzoj 3796 Mushroom追妹纸 —— 后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3796 先把三个串拼在一起,KMP 求 s1 , s2 中每个位置和 s3 的匹配情况: 注意 ...
- bzoj 3796: Mushroom追妹纸 AC自动机+后缀自动机+dp
题目大意: 给定三个字符串s1,s2,s3,求一个字符串w满足: w是s1的子串 w是s2的子串 s3不是w的子串 w的长度应尽可能大 题解: 首先我们可以用AC自动机找出s3在s1,s2中出现的位置 ...
- BZOJ 3796 Mushroom追妹纸 哈希+二分(+KMP)
先把两个串能匹配模式串的位置找出来,然后标记为$1$(标记在开头或末尾都行),然后对标记数组求一个前缀和,这样可以快速查到区间内是否有完整的一个模式串. 然后二分子串(答案)的长度,每次把长度为$md ...
- bzoj 3796: Mushroom追妹纸【二分+后缀数组+st表】
把三个串加上ASCII大于z的分隔符连起来,然后求SA 显然每个相同子串都是一个后缀的前缀,所以枚举s1的每个后缀的最长和s2相同的前缀串(直接在排序后的数组里挨个找,最近的两个分别属于s1和s2的后 ...
- 【BZOJ3796】Mushroom追妹纸 二分+hash
[BZOJ3796]Mushroom追妹纸 Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决 ...
- 【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分
Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意--写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从网上找到了两篇极佳的情书, ...
- BZOJ3796 : Mushroom追妹纸
将S1与S2用#号拼接在一起形成S串 将S3与S串跑KMP求出S3在S串中每次出现的位置l[i] 对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀 然后求出S串的后缀数组 先从小到大扫描 ...
随机推荐
- 代码中输入数字自动筛选出最大值,使用array,for loop and if (21.9.2017)
# include <stdio.h> # define N main(){ int a, b; ,,,,,,,,,,,,,,,,}; //array中输入需要排序的数字 ]; ; a & ...
- 卡尔曼滤波法C编程
float Angle = 0.0;//卡尔曼滤波器的输出值,最优估计的角度 //float Gyro_x = 0.0;//卡尔曼滤波器的输出值,最优估计的角速度 float Q_angle = 0. ...
- poj2029 Get Many Persimmon Trees
http://poj.org/problem?id=2029 单点修改 矩阵查询 二维线段树 #include<cstdio> #include<cstring> #inclu ...
- codeforces 830 B Cards Sorting
B. Cards Sorting http://codeforces.com/problemset/problem/830/B Vasily has a deck of cards consisti ...
- 从Nest到Nesk -- 模块化Node框架的实践
文: 达孚(沪江Web前端架构师) 本文原创,转至沪江技术 首先上一下项目地址(:>): Nest:https://github.com/nestjs/nest Nesk:https://git ...
- (function(root,factory){})(this,function($){}) 一个立即执行的匿名函数自调
因为新公司用到ocx 我就开始看原来的代码 无意中发现这个 可能原来比较low吗(虽然现在也很low吧)没发现这个东东 还可以这样写 于是乎我开始了探索 完整代码如下 HTML <div id= ...
- 【微软大法好】VS Tools for AI全攻略
大家都知道微软在Connect();17大会上发布了VS Tools for AI,旨在提升Visual Studio和VSCode对日益增长的深度学习需求的体验.看了一圈,网上似乎没有一个完整的中文 ...
- JAVA_SE基础——51.内部类
在Java中,允许在一个类的内部定义类,这样的类称作内部类,这个内部类所在的类称作外部类.根据内部类的位置.修饰符和定义的方式可分为成员内部类.静态内部类.方法(局部内部类)内部类. 内部类:一个类定 ...
- 如何深入系统的学习一门编程语言——python自学笔记
前言 最早接触python的时候,他并没有现在这么火,我也没把他太当回事,那时候我对python的印象就是给运维人员使用的一门很古老的语言,显然随着tensorflow(以下简称tf)的兴起,pyth ...
- Linux实战案例(6)yum查找、卸载、和安装软件
0.查找要安装的软件名字 yum search iostat就能查到以及iostat相干的安装包了, 别的想安装一个程序,只记得一部门名称,也可以用这个措施来实现安装 yum search png | ...