转博客大法好

自己画一画看一看,就会体会到这个设置关键点的强大之处了.

CODE(sa)

O(nlogn)→1436msO(nlogn)\to 1436msO(nlogn)→1436ms

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<class T>inline void read(T &num) {
register char ch; register int flg = 1;
while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar());
num *= flg;
}
const int MAXN = 5e4+5; int x[MAXN], y[MAXN], c[MAXN], Log[MAXN]; int n, s[MAXN], b[MAXN], tot;
struct SA {
int sa[MAXN], rk[MAXN], h[MAXN], f[MAXN][16];
inline void Get_Sa(int m) {
for(int i = 1; i <= m; ++i) c[i] = 0;
for(int i = 1; i <= n; ++i) ++c[x[i]=s[i]];
for(int i = 2; i <= m; ++i) c[i] += c[i-1];
for(int i = n; i >= 1; --i) sa[c[x[i]]--] = i;
for(int k = 1; k <= n; k<<=1) {
int p = 0;
for(int i = n-k+1; i <= n; ++i) y[++p] = i;
for(int i = 1; i <= n; ++i) if(sa[i]>k) y[++p] = sa[i]-k;
for(int i = 1; i <= m; ++i) c[i] = 0;
for(int i = 1; i <= n; ++i) ++c[x[i]];
for(int i = 2; i <= m; ++i) c[i] += c[i-1];
for(int i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i];
swap(x, y);
x[sa[1]] = 1; p = 1;
for(int i = 2; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] ==y[sa[i-1]+k]) ? p : ++p;
if((m=p) == n) break;
}
}
inline void Get_Height() {
int k = 0;
for(int i = 1; i <= n; ++i) rk[sa[i]] = i;
for(int i = 1; i <= n; ++i) {
if(rk[i] == 1) continue;
if(k) --k;
int j = sa[rk[i]-1];
while(i+k <= n && j+k <= n && s[i+k] == s[j+k]) ++k;
h[rk[i]] = k;
}
}
inline void rev() {
reverse(rk + 1, rk + n + 1);
for(int i = 1; i <= n; ++i) sa[i] = n-i+1;
}
inline void init() {
Get_Sa(n);
Get_Height();
}
inline void initST() {
for(int i = 1; i <= n; ++i) f[i][0] = h[i];
for(int j = 1; j <= Log[n]; ++j)
for(int i = 1; i <= n-(1<<j)+1; ++i)
f[i][j] = min(f[i][j-1], f[i+(1<<j-1)][j-1]);
}
inline int query(int l, int r) {
l = rk[l], r = rk[r];
if(l > r) swap(l, r);
++l;
int k = Log[r-l+1];
return min(f[l][k], f[r-(1<<k)+1][k]);
}
}sa1, sa2;
int m;
int main() {
read(n), read(m);
for(int i = 1; i <= n; ++i) read(s[i]);
--n;
for(int i = 1; i <= n; ++i) b[++tot] = (s[i]=s[i+1]-s[i]);
s[n+1] = 0;
sort(b + 1, b + tot + 1); tot = unique(b + 1, b + tot + 1) - b - 1;
for(int i = 1; i <= n; ++i) s[i] = lower_bound(b + 1, b + tot + 1, s[i]) - b; for(int i = 2; i <= n; ++i) Log[i] = Log[i>>1] + 1;
sa1.init(), sa1.initST();
reverse(s + 1, s + n + 1);
sa2.init(), sa2.rev(), sa2.initST();
LL ans = 0;
for(int len = 1; (len<<1)+m <= n; ++len)
for(int i = 1, j; (j=i+len+m) <= n; i += len) {
int l = min(sa2.query(i, j), len), r = min(sa1.query(i, j), len);
if(l + r > len) ans += l + r - len;
}
printf("%lld\n", ans);
}

CODE(hash)

O(nlog2n)→688msO(nlog^2n)\to 688msO(nlog2n)→688ms

实测hash速度是sa的2.5倍…

常数的幽怨…

市面上貌似找不到hash的代码的说…

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<class T>inline void read(T &num) {
register char ch; register int flg = 1;
while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar());
num *= flg;
}
const int MAXN = 5e4+5;
const int p = 137;
int n, m, s[MAXN], h[MAXN], mul[MAXN];
inline int hsh(int l, int r) {
return h[r] - h[l-1]*mul[r-l+1];
}
inline int querypre(int i, int j, int up) {
int l = 0, r = min(min(i, j), up), mid;
while(l < r) {
mid = (l + r + 1) >> 1;
if(hsh(i-mid+1, i) == hsh(j-mid+1, j)) l = mid;
else r = mid-1;
}
return l;
}
inline int querysuf(int i, int j, int up) {
int l = 0, r = min(min(n-i+1, n-j+1), up), mid;
while(l < r) {
mid = (l + r + 1) >> 1;
if(hsh(i, i+mid-1) == hsh(j, j+mid-1)) l = mid;
else r = mid-1;
}
return l;
}
int main() {
read(n), read(m); mul[0] = 1;
for(int i = 1; i <= n; ++i) read(s[i]);
for(int i = 1; i < n; ++i) {
h[i] = h[i-1] * p + s[i+1]-s[i];
mul[i] = mul[i-1] * p;
}
s[n] = 0; --n;
LL ans = 0;
for(int len = 1; (len<<1)+m <= n; ++len)
for(int i = 1, j; (j=i+len+m) <= n; i += len) {
int l = querypre(i, j, len), r = querysuf(i, j, len);
if(l + r > len) ans += l + r - len;
}
printf("%lld\n", ans);
}

BZOJ 2119: 股市的预测 (Hash / 后缀数组 + st表)的更多相关文章

  1. BZOJ 2119 股市的预测(后缀数组)

    首先要差分+离散化. 然后就是求形如ABA的串有多少,其中B的长度确定为k. 我们用到了设置关键点的思想.我们枚举A的长度L.然后在\(1,1+L,1+L*2,1+L*3...\)设置关键点.然后我们 ...

  2. bzoj千题计划312:bzoj2119: 股市的预测(后缀数组+st表)

    https://www.lydsy.com/JudgeOnline/problem.php?id=2119 题意:将给定数组差分后,求ABA形式的字串个数,要求|B|=m,|A|>0 1.后缀数 ...

  3. 【BZOJ 2119】 2119: 股市的预测 (后缀数组+分块+RMQ)

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 404  Solved: 188 Description 墨墨的妈妈热爱炒股,她 ...

  4. SPOJ 687 Repeats(后缀数组+ST表)

    [题目链接] http://www.spoj.com/problems/REPEATS/en/ [题目大意] 求重复次数最多的连续重复子串的长度. [题解] 考虑错位匹配,设重复部分长度为l,记s[i ...

  5. POJ 3693 Maximum repetition substring(后缀数组+ST表)

    [题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...

  6. BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay

    BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...

  7. UVA10829 L-Gap Substrings(后缀数组+ST表)

    后缀数组+ST表. 代填的坑. \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using namespace ...

  8. BZOJ 2119: 股市的预测 [后缀数组 ST表]

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 331  Solved: 153[Submit][Status][Discuss ...

  9. BZOJ 2119: 股市的预测 SA

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 434  Solved: 200[Submit][Status][Discuss ...

随机推荐

  1. 查找担保圈-step5-比较各组之间的成员,对组的包含性进行查询,具体见程序的注释-版本2

    USE [test] GO /****** Object: StoredProcedure [dbo].[p03_get_groupno_e2] Script Date: 2019/7/8 15:01 ...

  2. Linux系列(10):入门之bash基础与bash环境设置

    了解什么是shell吗? 知道如何查询当前系统支持的shell版本吗? 了解如何判断某个指令是否是bash的内置指令吗? 了解Linux的变量吗,知道如何定义与删除变量吗,知道如何赋值吗,知道如何获取 ...

  3. 后缀自动机----一种将字符串变成DAG的方法

    后缀自动机 (suffix automaton, SAM) 是一个能解决许多字符串相关问题的有力的数据结构.(否则我们也不会用它) 举几个例子,以下的字符串问题都可以在线性时间内通过 SAM 解决 1 ...

  4. PAT B1022 D进制的A+B

    课本AC代码 #include <cstdio> int main() { int a, b, d; scanf("%d%d%d", &a, &b, & ...

  5. gin框架博客实战教程2019web页面开发go语言实战博客开发

    视频教程: https://www.bilibili.com/video/av73698322?t=2400&p=5 资料下载地址(含数据库和main.go和controller里的代码) 注 ...

  6. python线程间通信

    #!/usr/bin/python # -*- coding:utf8 -*- from threading import Thread, Lock import random def test_th ...

  7. 【POI】使用POI 创建生成XLS,打开xls文件提示【此文件中某些文本格式可能已经更改,因为它已经超出最多允许的字体数。】

    使用POI 创建生成XLS,打开xls文件提示[此文件中某些文本格式可能已经更改,因为它已经超出最多允许的字体数.] 原因: 是因为在POI处理xls的过程中,太多次调用了: HSSFFont fon ...

  8. Spring 的 Bean 管理(注解方式)

    Spring 的 Bean 管理(注解方式) 1. 导入必要的 jar 包和 xml 文件 使用注解需要导入 spring-aop 的 jar 包. applicationContext.xml 文件 ...

  9. 你懂什么是分布式系统吗?Redis分布式锁都不会?

    分布式系统涉及到很多的技术.理论与协议,很多人也说,分布式系统是“入门容易,深入难”,有一些人简历上写着熟悉分布式系统,很多人都是管中窥豹只见一斑. 究竟什么是分布式系统? 分布式系统是由一组通过网络 ...

  10. 解决 Ubuntu 19 安装openjdk 8后与openjfx不兼容

    小淘气放假了,孩子在上幼儿园的小朋友,报班也不能太变态嘛, 还是让他自己娱乐的时间多一点,但是现在在家的娱乐就是看电视,听说电视看多了越看越傻,就想方设法的给他找一点娱乐活动,把我闲置的树莓派给他装了 ...