题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3796

先把三个串拼在一起,KMP 求 s1 , s2 中每个位置和 s3 的匹配情况;

注意拼三个串时加入的两个新字符不要一样,否则会影响;

然后预处理出每个位置后面的第一个 s3 的开头 —— 如果预处理结尾还得考虑它就在 s3 中的情况,易错...

然后正反做 s2 对 s1 的贡献,在 s1 处考虑不包含 s3 即可,反正 s1 和 s2 求了 LCP,是一样的;

还是得写得简洁优美,否则易错...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=1e5+1e4+,xm=1e4+;
int n,m,tax[xn],tp[xn],sa[xn],rk[xn],ht[xn][],bin[],bit[xn];
int l1,l2,l3,nxt[xn],f[xn],g[xn];
char a[xn],b[xn],s[xn],c[xm];
void getnxt()
{
for(int i=;i<=n;i++)
{
int nw=nxt[i-];
while(s[nw+]!=s[i]&&nw)nw=nxt[nw];
if(s[nw+]==s[i])nw++;
nxt[i]=nw;
if(nw>=l3)g[i-l3+]=;//i:start
}
for(int i=n+,lst=n+;i;i--)
{
if(g[i])lst=i;
f[i]=lst;
}
}
void Rsort()
{
for(int i=;i<=m;i++)tax[i]=;
for(int i=;i<=n;i++)tax[rk[tp[i]]]++;
for(int i=;i<=m;i++)tax[i]+=tax[i-];
for(int i=n;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];
}
void work()
{
for(int i=;i<=n;i++)rk[i]=s[i],tp[i]=i;
Rsort();
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;i++)tp[++num]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++num]=sa[i]-k;
Rsort(); swap(rk,tp);
rk[sa[]]=; num=;
for(int i=;i<=n;i++)
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[sa[i]+k]==tp[sa[i-]+k])?num:++num;
if(num==n)break;
m=num;
}
}
void get()
{
int k=;
for(int i=;i<=n;i++)
{
if(rk[i]==)continue;
if(k)k--; int j=sa[rk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
ht[rk[i]][]=k;
}
bin[]=; for(int i=;i<;i++)bin[i]=(bin[i-]<<);
bit[]=; for(int i=;i<=n;i++)bit[i]=bit[i>>]+;
for(int j=;j<;j++)
for(int i=;i<=n&&i+bin[j]-<=n;i++)
ht[i][j]=min(ht[i][j-],ht[i+bin[j-]][j-]);
}
int getlcp(int x,int y)
{
if(x==y)return n-x+;
x=rk[x]; y=rk[y];
if(x>y)swap(x,y); x++;
int w=bit[y-x+];
return min(ht[x][w],ht[y-bin[w]+][w]);
}
int main()
{
scanf("%s",a+); l1=strlen(a+);
scanf("%s",b+); l2=strlen(b+);
scanf("%s",c+); l3=strlen(c+);
n=l1+l2+l3+;
for(int i=;i<=l3;i++)s[i]=c[i]; s[l3+]='a'-;
for(int i=;i<=l1;i++)s[l3++i]=a[i]; s[l3+l1+]='a'-;//different
for(int i=;i<=l2;i++)s[l3+l1++i]=b[i];
getnxt();
n=l1++l2; m=;
for(int i=;i<=l1;i++)s[i]=a[i]; s[l1+]='a'-;
for(int i=;i<=l2;i++)s[l1++i]=b[i];
for(int i=;i<=n;i++)
{
f[i]=f[i+l3+]-l3-;/*
if(f[i]-l3+1<i)f[i]=f[i+l3+2]-l3-1;//!!
if(f[i]==n+1)f[i]=n+1;//same
else f[i]=f[i]-i;*/
}
work(); get();
int ans=;
for(int i=,tmp=;i<=n;i++)
{
int k=f[sa[i]]+l3--sa[i];
if(sa[i]<=l1)
{
ans=max(ans,min(tmp,k));
tmp=min(tmp,ht[i+][]);//+1
}
else if(sa[i]>l1+)//
tmp=ht[i+][];//
}
for(int i=n,tmp=;i;i--)
{
int k=f[sa[i]]+l3--sa[i];
if(sa[i]<=l1)
{
ans=max(ans,min(tmp,k));
tmp=min(tmp,ht[i][]);
}
else if(sa[i]>l1+)//
tmp=ht[i][];
}
printf("%d\n",ans);
return ;
}

bzoj 3796 Mushroom追妹纸 —— 后缀数组的更多相关文章

  1. bzoj 3796 Mushroom追妹纸——后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3796 长度一般都是 1e5 ,看这个是 5e4 ,一看就是把两个串接起来做. 自己本来想的是 ...

  2. [BZOJ 3796]Mushroom追妹纸

    [BZOJ 3796]Mushroom追妹纸 题目 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他 ...

  3. bzoj 3796: Mushroom追妹纸【二分+后缀数组+st表】

    把三个串加上ASCII大于z的分隔符连起来,然后求SA 显然每个相同子串都是一个后缀的前缀,所以枚举s1的每个后缀的最长和s2相同的前缀串(直接在排序后的数组里挨个找,最近的两个分别属于s1和s2的后 ...

  4. bzoj 3796: Mushroom追妹纸 AC自动机+后缀自动机+dp

    题目大意: 给定三个字符串s1,s2,s3,求一个字符串w满足: w是s1的子串 w是s2的子串 s3不是w的子串 w的长度应尽可能大 题解: 首先我们可以用AC自动机找出s3在s1,s2中出现的位置 ...

  5. ●BZOJ 3796 Mushroom追妹纸

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3796 题解: 题意:    给出三个串 A,B,C    找出一个最长串 S,    使得 ...

  6. BZOJ 3796 Mushroom追妹纸 哈希+二分(+KMP)

    先把两个串能匹配模式串的位置找出来,然后标记为$1$(标记在开头或末尾都行),然后对标记数组求一个前缀和,这样可以快速查到区间内是否有完整的一个模式串. 然后二分子串(答案)的长度,每次把长度为$md ...

  7. 【BZOJ3796】Mushroom追妹纸 二分+hash

    [BZOJ3796]Mushroom追妹纸 Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决 ...

  8. 【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分

    Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意--写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从网上找到了两篇极佳的情书, ...

  9. BZOJ3796 : Mushroom追妹纸

    将S1与S2用#号拼接在一起形成S串 将S3与S串跑KMP求出S3在S串中每次出现的位置l[i] 对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀 然后求出S串的后缀数组 先从小到大扫描 ...

随机推荐

  1. nyist oj 37 回文字符串 (动态规划经典)

    回文字符串 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描写叙述 所谓回文字符串,就是一个字符串.从左到右读和从右到左读是全然一样的.比方"aba".当 ...

  2. 小明同学喜欢体育锻炼,他常常去操场上跑步。跑道是一个圆形,在本题中,我们认为跑道是一个半径为R的圆形,设圆心的坐标原点(0,0)。小明跑步的起点坐标为(R,0),他沿着圆形跑道跑步,而且一直沿着一个方向跑步。回到家后,他查看了自己的计步器,计步器显示他跑步的总路程为L。小明想知道自己结束跑步时的坐标,但是他忘记自己是沿着顺时针方向还是逆时针方向跑的了。他想知道在这两种情况下的答案分别是多少。

    include "stdafx.h" #include<iostream> #include<vector> #include<string> ...

  3. 下一代Apache Hadoop MapReduce框架的架构

    背景 随着集群规模和负载增加,MapReduce JobTracker在内存消耗,线程模型和扩展性/可靠性/性能方面暴露出了缺点,为此需要对它进行大整修. 需求 当我们对Hadoop MapReduc ...

  4. Linux进入单用户模式

    有时候配置linux的过程中,因为一些误操作导致系统初始化时堵塞或挂起而无法进入系统,原因往往是因为配置文件设置错误,部分文件被误删之类.遇到这种情况一般新手的做法就是重装(虚拟机不装白不装),但在实 ...

  5. 在另一个线程中无法用((CMainFrame *)AfxGetMainWnd())

    一个vc6的项目放到vc8下重新编译这里死活过不去 查了些资料无果后来翻到一句老外的回答 If AfxGetMainWnd is called from the application’s prima ...

  6. 2015年多校联合训练第一场OO’s Sequence(hdu5288)

    题意:给定一个长度为n的序列,规定f(l,r)是对于l,r范围内的某个数字a[i],都不能找到一个相应的j使得a[i]%a[j]=0.那么l,r内有多少个i,f(l,r)就是几. 问全部f(l,r)的 ...

  7. 14、AppWidget及Launcher RemoteViews

    一.Launcher的简单研究 1 什么是Launcher Android系统启动后加载的第一个程序 . 这个程序是其他应用程序的入口 . Launcher构成: HomeScreen : (Work ...

  8. Chrome 的滚动条修改.

    该方法针对于win下Chrome任何版本(未测试基于Chrome内核的其他浏览器),Lunix就是目录换了一下 目录是:**\Google\Chrome\User Data\Profile 2\Use ...

  9. 扩容数据盘_Linux

    扩容数据盘_Linux_扩容云盘_云盘_用户指南_云服务器 ECS-阿里云 https://help.aliyun.com/document_detail/25452.html 磁盘扩容付费后: 在控 ...

  10. C语言实现 操作系统 银行家算法

    /**************************************************** 银行家算法 算法思想: 1. 在多个进程中,挑选资源需求最小的进程Pmin. 可能存在多类资 ...