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;}
原创粉丝点击