zoukankan      html  css  js  c++  java
  • 【BZOJ3796】Mushroom追妹纸 二分+hash

    【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;
    }
  • 相关阅读:
    linux2.6.37内核接两个硬盘导致读写效率变低的问题
    使用kprobes查看内核内部信息
    linux下内存大小、起始地址的解析与修改
    docker fastadmin
    JAVAEE——BOS物流项目11:在realm中授权、shiro的方法注解权限控制、shiro的标签权限控制、总结shiro的权限控制方式、权限管理
    mysql 错误解决:Plugin 'FEDERATED' is disabled. /usr/sbin/mysqld: Table 'mysql.plugin' doesn't exist
    JAVAEE——BOS物流项目10:权限概述、常见的权限控制方式、apache shiro框架简介、基于shiro框架进行认证操作
    错误解决:HibernateSystemException-HHH000142: Javassist Enhancement failed
    JAVAEE——BOS物流项目09:业务受理需求分析、创建表、实现自动分单、数据表格编辑功能使用方法和工作单快速录入
    JAVAEE——BOS物流项目08:配置代理对象远程调用crm服务、查看定区中包含的分区、查看定区关联的客户
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7412167.html
Copyright © 2011-2022 走看看