【BZOJ3796】Mushroom追妹纸

Description

Mushroom最近看上了一个漂亮妹纸。他选择一种非常经典的手段来表达自己的心意——写情书。考虑到自己的表达能力,Mushroom决定不手写情书。他从网上找到了两篇极佳的情书,打算选择其中共同的部分。另外,Mushroom还有个一个情敌Ertanis,此人也写了封情书给妹子。
Mushroom不希望自己的情书中完整的出现了情敌的情书。(这样抄袭的事情就暴露了)。
Mushroom把两封情书分别用字符串s1和s2来表示,Ertanis的情书用字符串s3来表示,他要截取的部分用字符串w表示。
需满足:
1、w是s1的子串
2、w是s2的子串
3、s3不是w的子串
4、w的长度应尽可能大
所谓子串是指:在字符串中连续的一段
【输入】
输入文件为girl.in
输入有三行,第一行为一个字符串s1第二行为一个字符串s2, 
第三行为一个字符串s3。输入仅含小写字母,字符中间不含空格。
【输出】
输出文件为girl.out
输出仅有一行,为w的最大可能长度,如w不存在,则输出0。
【输入样例】
abcdef
abcf
bc
【输出样例】
2
【样例解释】
s1和s2的公共子串有abc,ab,bc,a,b,c,f,其中abc,bc包含子串bc不合法,所以最长的合法子串为ab。
【数据规模】
对于30%的数据:1<=s1、s2、s3的长度<=500
对于60%的数据:1<=s1、s2、s3的长度<=5000
对于100%的数据:1<=s1、s2的长度<=50000,1<=s3的长度<=10000

Input

输入有三行,第一行为一个字符串s1第二行为一个字符串s2, 
第三行为一个字符串s3。输入仅含小写字母,字符中间不含空格。

Output

输出仅有一行,为w的最大可能长度,如w不存在,则输出0。

Sample Input

abcdef
abcf
bc

Sample Output

2
【样例解释】
s1和s2的公共子串有abc,ab,bc,a,b,c,f,其中abc,bc包含子串bc不合法,所以最长的合法子串为ab。

HINT

对于100%的数据:1<=s1、s2的长度<=50000,1<=s3的长度<=10000

题解:“没有什么字符串问题是hash解决不了的。”

先用hash找出s3在s1中所有出现的位置,把这些位置都打上危险标记。显然答案是可二分的,于是二分答案。假设当前二分的答案为len,我们将s2中所有长度为len的子串的hash值都拿出来,扔到set里,我们再枚举s1中所有长度为len的子串,如果当前子串再set中出现过,并且当前串中不包含危险标记,则该串是符合要求的。

此外,望大家学习正确的重载运算符的姿势,并养成良好的习惯啊~(当你看见编译时反馈的一大坨信息你就洒sha了。)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <set>
#include <utility>
using namespace std;
const int maxn=50010;
typedef long long ll;
const ll m1=998244353;
const ll m2=1000000007;
struct pll
{
ll F,S;
pll() {}
pll(ll a,ll b){F=a,S=b;}
pll operator * (const ll &b) const {return pll(F*b%m1,S*b%m2);}
pll operator + (const ll &b) const {return pll((F+b)%m1,(S+b)%m2);}
pll operator * (const pll &b) const {return pll(F*b.F%m1,S*b.S%m2);}
pll operator - (const pll &b) const {return pll((F-b.F+m1)%m1,(S-b.S+m2)%m2);}
bool operator < (const pll &b) const {return (F==b.F)?(S<b.S):(F<b.F);}
bool operator == (const pll &b) const {return F==b.F&&S==b.S;}
}h1[maxn],h2[maxn],h3,bs[maxn];
int l1,l2,l3;
char s1[maxn],s2[maxn],s3[maxn];
set<pll> s;
int dan[maxn];
bool solve(int l)
{
int i;
s.clear();
for(i=l;i<=l2;i++) s.insert(h2[i]-(h2[i-l]*bs[l]));
for(i=l;i<=l1;i++)
{
if((l<l3||!(dan[i]-dan[i-l+l3-1]))&&s.find(h1[i]-(h1[i-l]*bs[l]))!=s.end()) return 1;
}
return 0;
}
int main()
{
scanf("%s%s%s",s1,s2,s3),l1=strlen(s1),l2=strlen(s2),l3=strlen(s3);
int i;
for(bs[0]=pll(1,1),i=1;i<=max(l1,l2);i++) bs[i].F=bs[i-1].F*233%m1,bs[i].S=bs[i-1].S*233%m2;
for(i=1;i<=l1;i++) h1[i]=(h1[i-1]*233)+s1[i-1];
for(i=1;i<=l2;i++) h2[i]=(h2[i-1]*233)+s2[i-1];
for(i=1;i<=l3;i++) h3=(h3*233)+s3[i-1];
for(i=l3;i<=l1;i++) if(h1[i]-(h1[i-l3]*bs[l3])==h3) dan[i]=1;
for(i=1;i<=l1;i++) dan[i]+=dan[i-1];
int l=1,r=min(l1,l2)+1,mid;
while(l<r)
{
mid=(l+r)>>1;
if(solve(mid)) l=mid+1;
else r=mid;
}
printf("%d",l-1);
return 0;
}

【BZOJ3796】Mushroom追妹纸 二分+hash的更多相关文章

  1. BZOJ3796 Mushroom追妹纸(二分答案+后缀数组+KMP)

    求出一个串使得这个串是\(s1,s2\)的子串.串中不包含\(s3\). 如果没有这个\(s3\)就可以二分答案,然后height小于二分值分一组.看看每组里是不是出现过\(s1,s2\)的后缀.判断 ...

  2. BZOJ3796 Mushroom追妹纸 字符串 SA KMP

    原文链接https://www.cnblogs.com/zhouzhendong/p/9253173.html 题目传送门 - BZOJ3796 题意 找一个串 $w$ 满足: 1.$w$ 是 $s_ ...

  3. BZOJ3796 : Mushroom追妹纸

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

  4. [BZOJ3796]Mushroom追妹纸:后缀自动机+KMP

    分析 这道题有个\(O(n)\)的后缀自动机做法,感觉很好理解就在这说一下. 先对\(s1\)和\(s2\)求最长公共子串,对于\(s2\)的每一个下标\(i\),求一个\(f[i]\)表示以\(s2 ...

  5. [BZOJ 3796]Mushroom追妹纸

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

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

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

  7. 【bzoj3796】Mushroom追妹纸 Kmp+二分+Hash

    题目描述 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. 4.w的长度应尽可能大 求w的最大长度. 输入 输入有三行,第一行为 ...

  8. 【bzoj3796】Mushroom追妹纸

    Portal -->bzoj3796 Description 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. ​ 求w的 ...

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

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

随机推荐

  1. LeetCode OJ-- Container With Most Water

    https://oj.leetcode.com/problems/container-with-most-water/ 不同高度的柱子排一列,两个柱子可以组成一个容器,求最大容积. 最直观的方法就是暴 ...

  2. 解决mysql 远程链接问题

    grant all privileges on *.* to 'root'@'192.168.2.204' identified by '123456' with grant option;flush ...

  3. 在Android 7.0以上PopupWindow.showAsDropDown()不起作用问题

    最近优化界面,调用PopupWindow.showAsDropDown()发现,窗口并没有在控件下方显示. 有网友说是7.0以上系统的问题,可以自定义PopupWindow,重写showAsDropD ...

  4. HDU 5869.Different GCD Subarray Query-区间gcd+树状数组 (神奇的标记右移操作) (2016年ICPC大连网络赛)

    树状数组... Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/6 ...

  5. Codeforces 746G(构造)

                                                                                                      G. ...

  6. [原创]Getting Started with Skywalking

    Getting Started with Skywalking Pre JDK 1.8+ Skywalking(v3.2.6) (All packages can be download from G ...

  7. 苹果开发者:Siri未开放API 有些让人失望

    北京时间6月12日消息,据国外媒体报道,苹果公司在WWDC大会上展示了新版iOS和OS X系统,但由于未开放Siri API,一些苹果开发者还是有些失望. Siri API可以让开发者在自己的应用中整 ...

  8. FORM标准默认时间区间处理

    WHEN-NEW-FORM-INSTANCE DECLARE    temp_date         date;    client_timezone   date;    char_date    ...

  9. HPU 3639--Hawk-and-Chicken【SCC缩点反向建图 &amp;&amp; 求传递的最大值】

    Hawk-and-Chicken Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  10. cocos2d-x 学习记录

    不积跬步,无以至千里.不积小流,无以成江海. 開始学习cocos2d-x ,路漫漫其修远兮.加油!