BZOJ 3796: Mushroom追妹纸 哈希+二分
来源:互联网 发布:阿铭linux 视频 云盘 编辑:程序博客网 时间:2024/06/05 21:49
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
题解
首先做一遍kmp,把A串和B串中包含C串的最后一个点标记成1,然后对这个东西求一个前缀和,就能快速知道一段区间内有没有关键点,然后我们二分答案mid,将A串中所有长度为mid的子串的哈希值加入到map中,扫B串长度为mid的子串,查看哈希值有没有出现过,如果有证明有长度为mid的串。(作死写了双哈希,好像没什么卵用)
#include<cstdio>#include<cstdlib>#include<ctime>#include<cmath>#include<algorithm>#include<iostream>#include<iomanip>#include<cstring>#include<string>#include<map>using namespace std;char s1[100000];char s2[100000];char s3[100000];int Hash1s1[100000];int Hash2s1[100000];int Hash1s2[100000];int Hash2s2[100000];int len1,len2,len3;const int MOD1=23333333;const int MOD2=10000007;int base1[100000];int base2[100000];map<int,bool> mapp1,mapp2;int nex[100000];int pd1[100000];int pd2[100000];void kmp(){ int fix=0; for(int i=2;i<=len3;i++) { while(fix && s3[fix+1]!=s3[i]) fix=nex[fix]; if(s3[fix+1]==s3[i]) fix++; nex[i]=fix; } fix=0; for(int i=1;i<=len1;i++) { while(fix && s3[fix+1]!=s1[i]) fix=nex[fix]; if(s3[fix+1]==s1[i]) fix++; if(fix==len3) { pd1[i]=1; fix=nex[fix]; } pd1[i]+=pd1[i-1]; } fix=0; for(int i=1;i<=len2;i++) { while(fix && s3[fix+1]!=s2[i]) fix=nex[fix]; if(s3[fix+1]==s2[i]) fix++; if(fix==len3) { pd2[i]=1; fix=nex[fix]; } pd2[i]+=pd2[i-1]; }}bool check(int mid){ mapp1.clear(); mapp2.clear(); for(int i=1;i+mid-1<=len1;i++) { if(mid>=len3 && pd1[i+mid-1]-pd1[i+len3-2]>0) continue; int hash1=Hash1s1[i+mid-1]-1ll*Hash1s1[i-1]*base1[mid]%MOD1; hash1+=MOD1; hash1%=MOD1; int hash2=Hash2s1[i+mid-1]-1ll*Hash2s1[i-1]*base2[mid]%MOD2; hash2+=MOD2; hash2%=MOD2; mapp1[hash1]=true; mapp2[hash2]=true; } for(int i=1;i+mid-1<=len2;i++) { if(mid>=len3 && pd2[i+mid-1]-pd2[i+len3-2]>0) continue; int hash1=Hash1s2[i+mid-1]-1ll*Hash1s2[i-1]*base1[mid]%MOD1; hash1+=MOD1; hash1%=MOD1; int hash2=Hash2s2[i+mid-1]-1ll*Hash2s2[i-1]*base2[mid]%MOD2; hash2+=MOD2; hash2%=MOD2; if(mapp1[hash1] && mapp2[hash2]) return true; } return false;}int main(){ scanf("%s%s%s",s1+1,s2+1,s3+1); len1=strlen(s1+1); len2=strlen(s2+1); len3=strlen(s3+1); base1[0]=1; base2[0]=1; int Maxx=max(len1,len2); for(int i=1;i<=Maxx;i++) base1[i]=1ll*base1[i-1]*27%MOD1,base2[i]=1ll*base2[i-1]*233%MOD2; for(int i=1;i<=len1;i++) { Hash1s1[i]=(1ll*Hash1s1[i-1]*base1[1]+s1[i]-'a'+1)%MOD1; Hash2s1[i]=(1ll*Hash2s1[i-1]*base2[1]+s1[i]-'a'+1)%MOD2; } for(int i=1;i<=len2;i++) { Hash1s2[i]=(1ll*Hash1s2[i-1]*base1[1]+s2[i]-'a'+1)%MOD1; Hash2s2[i]=(1ll*Hash2s2[i-1]*base2[1]+s2[i]-'a'+1)%MOD2; } kmp(); int l=1,r=min(len1,len2); int jilu=0; while(l<=r) { int mid=l+r>>1; if(check(mid)) jilu=mid,l=mid+1; else r=mid-1; } cout<<jilu<<endl; return 0;}
- BZOJ 3796: Mushroom追妹纸 哈希+二分
- bzoj-3796 Mushroom追妹纸
- BZOJ 3796 Mushroom追妹纸 后缀数组+KMP
- bzoj 3796 Mushroom追妹纸 后缀数组 kmp
- 【bzoj3796】Mushroom追妹纸 hash+二分答案
- bzoj3796 Mushroom追妹纸(SA+二分答案+kmp)
- bzoj 1199 二分暴力
- bzoj 1692 二分+hash
- BZOJ 2821 分块+二分
- bzoj 2016 二分答案
- bzoj 2348 二分
- BZOJ 1196 二分+Kruskal
- bzoj 1271 二分
- bzoj 3412 二分
- BZOJ-5090 (二分答案)
- Mushroom Scientists
- Mushroom Introduction
- BZOJ 4025 二分图 LCT
- 剑指Offer——计算1至n中数字x出现的次数
- java删除文件夹下的所有文件
- 集群技术(一)nginx1.1 -- nginx安装
- 复习
- An Introduction to CNN based Object Detection
- BZOJ 3796: Mushroom追妹纸 哈希+二分
- 算法导论 练习题 17.2-3
- Git之删除文件
- 给定一个字符串,返回字符串中没有重复字符的最长子串的长度
- oracle 动态执行命令execute immediate
- 解密:Linux与Android的关系
- 共享单车上的智能锁,做出来有多难?
- POST 方法总结
- 数组的声明定义以及基础知识详解