SYZOJP186 你猜猜是不是DP题解

题目传送门

现在给两个仅包含小写字母的字符串a,b ,求a 与b的最长公共连续子串的长度。

对于20%的数据,a,b长度 ∈ [1, 200]

对于50%的数据,a,b长度 ∈ [1, 20000]

对于100%的数据, a,b长度 ∈ [1, 200000]

分析

根据数据规模,DP肯定是要GG的

应该是要用比较神奇的字符串算法,但是本题猪油一组测试数据,经过计算,发现二分答案+hash函数可以通过。

做法

  1. 此题可以二分答案长度len

    1. 计算两个字符串各个起点长度为len的子串hash得两hash数组A,B。并从大到小排序。
    2. 两个指针p,q分别指向A,B数组。从前往后扫描。
      1. 如果p,q所指元素hash相等。

        a. A数组中所有hash值和p所指元素相同的元素构成的集合为AA。

        b. 同理有集合BB。

        c. AA和BB的集合都需要两两检验是否有相同子串。

        d. 有则标记跳出。

        e. 若都无,p,q后移。
      2. 不相等,则hash值大者后移。

复杂度

排序

O(Llog2L)" role="presentation">O(Llog2L)O(Llog2L)

总的期望

O(Llog22L)" role="presentation">O(Llog22L)O(Llog22L)

貌似如果AA集合和BB集合都含有大量元素,规模相当于O(L)" role="presentation" style="position: relative;">O(L)O(L) ,且实际上每个字串优势不想等的则复杂度就O(L2log2L)" role="presentation" style="position: relative;">O(L2log2L)O(L2log2L)

但这种出现的概率应当是比中五百万彩票还要小

以此O(Llog22L)" role="presentation" style="position: relative;">O(Llog22L)O(Llog22L)再与108" role="presentation" style="position: relative;">108108相比得0.35左右。故应当可以AC

/*
653 ms 6500 K C++ / 2.1 K
*/
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
void hash(string &s,ULL h[],ULL g[],ULL C)
{
h[s.length()]=0;
for (int i=s.length()-1;i>=0;--i)
h[i]=h[i+1]*C+s[i];
g[0]=1;
for (size_t i=1;i<=s.length();++i)
g[i]=g[i-1]*C;
} ULL sub_hash(int i,int j,ULL h[],ULL g[])//[i,j)
{
return h[i]-h[j]*g[j-i];
}
const int maxl=200005;
string a,b;
ULL ga[maxl],ha[maxl],gb[maxl],hb[maxl];
ULL C=131;
struct nd{
ULL h;
int i;
}A[maxl],B[maxl];
bool operator <(nd a,nd b)
{
return a.h>b.h;
}
int main()
{
int ans,l,r,m,len,la,lb,ka,kb;
cin>>a>>b;
hash(a,ha,ga,C);
hash(b,hb,gb,C);
la=a.length(); lb=b.length();
l=0; r=min(la,lb)+1;
//ans is in [l,r)
while (l+1<r) {
len=m=(l+r+1)/2;
ka=la-len+1; kb=lb-len+1;
for (int i=0;i<ka;++i) {
A[i].i=i;
A[i].h=sub_hash(i,i+len,ha,ga);
}
for (int i=0;i<kb;++i) {
B[i].i=i;
B[i].h=sub_hash(i,i+len,hb,gb);
}
sort(A,A+ka);
sort(B,B+kb);
bool ok=false;
int p=0,q=0;
int same_ar,same_br;
int u,v;
while (!ok&&p<ka&&q<kb) {
if (A[p].h==B[q].h) {
for (same_ar=p+1;same_ar<ka;++same_ar) if (A[p].h!=A[same_ar].h) break;
for (same_br=q+1;same_br<kb;++same_br) if (B[q].h!=B[same_br].h) break;
for (u=p;!ok&&u<same_ar;u++)
for (v=q;v<same_br;v++)
if (a.substr(A[u].i,len)==b.substr(B[v].i,len)) {
ok=true;break;
}
p=same_ar;q=same_br;
} else if (A[p].h>B[q].h) {
++p;
} else {
++q;
}
}
if (ok) {
l=m;
} else {
r=m;
}
}
ans=l;
cout<<ans<<endl;
}

SYZOJP186 你猜猜是不是DP 二分+hash解法的更多相关文章

  1. CF#633C Spy Syndrome 2 DP+二分+hash

    Spy Syndrome 2 题意 现在对某个英文句子,进行加密: 把所有的字母变成小写字母 把所有的单词反过来 去掉单词之间的空格 比如:Kira is childish and he hates ...

  2. 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 题目大意: 给一棵树,n个节点,每条边有个权值,从每个点i出发有个不经过自己走过的点的最远距离 ...

  3. hdu 1025:Constructing Roads In JGShining's Kingdom(DP + 二分优化)

    Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65 ...

  4. YbtOJ#526-折纸游戏【二分,hash】

    正题 题目链接:https://www.ybtoj.com.cn/problem/526 题目大意 一个\(n\times m\)的网格上有字母,你每次可以沿平行坐标轴对折网格,要求对折的对应位置字母 ...

  5. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6243  Solved: 2007[Submit] ...

  6. HDU 3433 (DP + 二分) A Task Process

    题意: 有n个员工,每个员工完成一件A任务和一件B任务的时间给出,问要完成x件A任务y件B任务所需的最短时间是多少 思路: DP + 二分我也是第一次见到,这个我只能说太难想了,根本想不到. dp[i ...

  7. POJ-2533最长上升子序列(DP+二分)(优化版)

    Longest Ordered Subsequence Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 41944   Acc ...

  8. hdu2993之斜率dp+二分查找

    MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. poj3208 Apocalypse Someday 数位dp+二分 求第K(K <= 5*107)个有连续3个6的数。

    /** 题目:poj3208 Apocalypse Someday 链接:http://poj.org/problem?id=3208 题意:求第K(K <= 5*107)个有连续3个6的数. ...

随机推荐

  1. [Redis-CentOS7]Redis打开远程连接(十) Could not connect to Redis at 127.0.0.1:6379: Connection refused

    通过网络无法访问Redis redis-cli 172.16.1.111 Could not connect to Redis at 127.0.0.1:6379: Connection refuse ...

  2. Day3前端学习之路——CSS基本知识

    课程目标 初步了解什么是CSS,掌握基本的CSS概念,语法,针对选择器特殊性的计算处理,以及学习如何设置一些简单的样式 任务一:回答问题 1.什么是CSS,CSS是如何工作的? CSS 指层叠样式表 ...

  3. CVE-2020-0618 SQL 远程代码执行

    CVE-2020-0618 SQL Server远程代码执行 1.简介 SQL Server Reporting Services(SSRS)提供了一组本地工具和服务,用于创建,部署和管理移动报告和分 ...

  4. Vue-20190623点滴

    Vue-20190623点滴 推荐黄奕同学vue的学习方式和过程. https://juejin.im/post/5b18d2d7f265da6e410e0e20 ♣♣♣♣♣♣♣♣♣♣♣♣♣♣♣♣♣♣ ...

  5. codewars--js--create phone number

    Write a function that accepts an array of 10 integers (between 0 and 9), that returns a string of th ...

  6. html语义化的意义

    易于用户阅读,样式丢失的时候能让页面呈现清晰的结构. 有利于SEO,搜索引擎根据标签来确定上下文和各个关键字的权重. 方便其他设备解析,如盲人阅读器根据语义渲染网页 有利于开发和维护,语义化更具可读性 ...

  7. WinFrom 在Devexpress里用GridControl和DataNavigtor进行分页

    1,分页嘛先要有个SQL 程序才能写下去 先提供下SQL的思路,对于分页的SQL我之前帖子有介绍,就不一一介绍了 select top pageSize * --显示数量 from (select r ...

  8. git系列之---将本地的项目添加到码云仓库

    1.前情: 本地写的 Demo 传到码云上面进行维护. 2.操作步骤: git init   将本地文件初始化为git 仓库,文件件会多一个 .git 文件夹[版本库]: git add .   或者 ...

  9. Electron – 基础学习(3): 项目打包成exe桌面应用 之electron-builder

    前次用 electron-packager 打包成功,这次改用 electron-builder 打包,然后根据项目中实际需要进行选择使用. 第一步:全局安装 electron-builder,便于系 ...

  10. count(1)比count(*)效率高?

    SELECT COUNT(*) FROM table_name是个再常见不过的统计需求了. 本文带你了解下Mysql的COUNT函数. 一.COUNT函数 关于COUNT函数,在MySQL官网中有详细 ...