Description

墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势。股票折线图是研究股票的必备工
具,它通过一张时间与股票的价位的函数图像清晰地展示了股票的走势情况。经过长时间的观测,墨墨发现很多股
票都有如下的规律:之前的走势很可能在短时间内重现!如图可以看到这只股票A部分的股价和C部分的股价的走势
如出一辙。通过这个观测,墨墨认为他可能找到了一个预测股票未来走势的方法。进一步的研究可是难住了墨墨,
他本想试图统计B部分的长度与发生这种情况的概率关系,不过由于数据量过于庞大,依赖人脑的力量难以完成,
于是墨墨找到了善于编程的你,请你帮他找一找给定重现的间隔(B部分的长度),有多少个时间段满足首尾部分
的走势完全相同呢?当然,首尾部分的长度不能为零。

Input

第一行包含两个整数N、M,分别表示需要统计的总时间以及重现的间隔(B部分的长度)。
接下来N行,每行一个整数,代表每一个时间点的股价。
4≤N≤50000 1≤M≤10 M≤N 所有出现的整数均不超过32位含符号整数。

Output

输出一个整数,表示满足条件的时间段的个数

Sample Input

12 4
1 2 3 4 8 9 1 2 3 4 8 9

Sample Output

6

解题思路:

还是很佩服后缀数组的思维。

这是求一个具有ABA结构的字符串个数。

发现一个性质,如果左右A足够长,

就可以将中间部分左右移动得到新答案。

枚举A的长度L,按L分块,边缘设为关键点。

易知关键点只能被一个串覆盖一次。

只需正反构建后缀数组求Lcp即可。

时间复杂度n(lnn+logn)

代码:

 #include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=;
struct Sa{
int sa[N];
int tmr[N];
int rnk[N];
int has[N];
int str[N];
int hgt[N];
int Rmq[][N];
int lg[N];
int cnt;
int n;
bool Same(int a,int b,int l)
{
if(a+l>n||b+l>n)
return false;
return (rnk[a]==rnk[b])&&(rnk[a+l]==rnk[b+l]);
}
void Insert(int *a,int len)
{
for(int i=;i<=len;i++)
str[i]=a[i];
n=len;
return ;
}
void Reverse(int *a,int len)
{
int j=;
for(int i=len;i;i--)
str[++j]=a[i];
n=len;
return ;
}
void Build(void)
{
for(int i=;i<=n;i++)
lg[i]=lg[i/]+;
for(int i=;i<=n;i++)
has[str[i]]++;
for(int i=;i<=n;i++)
if(has[i])
tmr[i]=++cnt;
for(int i=;i<=n;i++)
has[i]+=has[i-];
for(int i=;i<=n;i++)
{
sa[has[str[i]]--]=i;
rnk[i]=tmr[str[i]];
}
for(int k=;cnt!=n;k<<=)
{
cnt=;
for(int i=;i<=n;i++)
has[i]=;
for(int i=;i<=n;i++)
has[rnk[i]]++;
for(int i=;i<=n;i++)
has[i]+=has[i-];
for(int i=n;i;i--)
if(sa[i]>k)
tmr[sa[i]-k]=has[rnk[sa[i]-k]]--;
for(int i=;i<=k;i++)
tmr[n-i+]=has[rnk[n-i+]]--;
for(int i=;i<=n;i++)
sa[tmr[i]]=i;
for(int i=;i<=n;i++)
if(Same(sa[i],sa[i-],k))
tmr[sa[i]]=cnt;
else
tmr[sa[i]]=++cnt;
for(int i=;i<=n;i++)
rnk[i]=tmr[i];
}
for(int i=;i<=n;i++)
{
if(rnk[i]==)
continue;
int j=std::max(,hgt[rnk[i-]]-);
while(str[i+j-]==str[sa[rnk[i]-]+j-])
hgt[rnk[i]]=j++;
}
for(int i=;i<=n;i++)
Rmq[][i]=hgt[i];
for(int i=;i<=;i++)
for(int j=;j+(<<i)-<=n;j++)
Rmq[i][j]=std::min(Rmq[i-][j],Rmq[i-][j+(<<(i-))]);
return ;
}
int Lcp(int i,int j)
{
i=rnk[i],j=rnk[j];
if(j<i)
i^=j^=i^=j;
i++;
int l=lg[j-i+];
return std::min(Rmq[l][i],Rmq[l][j-(<<l)+]);
}
}S1,S2;
int tmp[N];
int sln[N];
int n,B;
std::map<int,int>M;
int main()
{
//freopen("a.in","r",stdin);
scanf("%d%d",&n,&B);
int cnt=;
for(int i=;i<=n;i++)
scanf("%d",&sln[i]);
for(int i=n;i>=;i--)
sln[i]-=sln[i-];
for(int i=;i<=n;i++)
{
if(M.find(sln[i])==M.end())
M[sln[i]]=++cnt;
tmp[i-]=M[sln[i]];
}
S1.Insert(tmp,n-);
S2.Reverse(tmp,n-);
S1.Build();
S2.Build();
int ans=;
for(int L=;L<=((n-)-B)/;L++)
{
for(int i=;i<=n-;i+=L)
{
int j=i+B+L;
if(j>n-)
continue;
int r=std::min(L,S1.Lcp(i,j));
int l=std::min(L,S2.Lcp(n-i,n-j));
int t=l+r-;
if(t>=L)
ans+=t-L+;
}
}
printf("%d\n",ans);
return ;
}

BZOJ2119: 股市的预测(后缀数组)的更多相关文章

  1. 【BZOJ2119】股市的预测 后缀数组+分块

    [BZOJ2119]股市的预测 Description 墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势.股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰 ...

  2. 【BZOJ-2119】股市的预测 后缀数组

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

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

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

  4. BZOJ 2119 股市的预测 (后缀数组+RMQ)

    题目大意:求一个字符串中形如$ABA$的串的数量,其中$B$的长度是给定的 有点像[NOI2016]优秀的拆分这道题 先对序列打差分,然后离散,再正反跑$SA$,跑出$st$表 进入正题 $ABA$串 ...

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

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

  6. [NOI2016]优秀的拆分&&BZOJ2119股市的预测

    [NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...

  7. BZOJ2119 股市的预测 字符串 SA ST表

    原文链接https://www.cnblogs.com/zhouzhendong/p/9069171.html 题目传送门 - BZOJ2119 题意 给定一个股票连续$n$个时间点的价位,问有多少段 ...

  8. bzoj2119 股市的预测

    传送门 感觉智商莫名其妙的就变低了……写这题的时候死活想不出来…… 做法其实不难…… 题目要求形如ABA的串的个数,我们可以枚举A的长度,利用标记关键点的方法统计答案.设枚举到的答案为k,每k个点标记 ...

  9. bzoj 4650(洛谷 1117) [Noi2016]优秀的拆分——枚举长度的关键点+后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 ...

随机推荐

  1. JAVA并发--volatile

    学过计算机组成原理的一定知道,为了解决内存速度跟不上CPU速度这个问题,在CPU的设计中加入了缓存机制,缓存的速度介于CPU和主存之间.在进行运算的时候,CPU将需要的数据映射一份在缓存中,然后直接操 ...

  2. thinkphp5项目--企业单车网站(六)

    thinkphp5项目--企业单车网站(六) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...

  3. orm 通用方法——QueryModelCount条件查询记录数

    定义代码: /** * 描述:根据条件查询对象数 * 作者:Tianqi * 日期:2014-09-17 * param:model 对象实例 * param:cond 查询条件 * return:i ...

  4. Linux远程远程控制程序TeamViewer

    TeamViewer 软件我就不介绍了,相信进行远程管理的人都知道它. 1.安装: Linux个发行版因软件管理方式不同而不同,先通过软件管理从自己的软件仓库进行搜索安装如果有就进行安装,没有通过官网 ...

  5. HDU 4431 Mahjong 模拟

    http://acm.hdu.edu.cn/showproblem.php?pid=4431 不能说是水题了,具体实现还是很恶心的...几乎优化到哭但是DFS(还加了几个剪枝)还是不行...搜索一直T ...

  6. webstorm配置less解析的方法

    1.安装node.js 2.npm 安装less, npm install -g less 2.1 lessc style.less styles.css 编译 2.2 lessc –clean-cs ...

  7. js中迭代的常用几种方法

    var arr = [1,3,2,5,3]; //forEach 两个参数,第一个为数组内容,第二个为数组下标arr.forEach(function(item,index) { console.lo ...

  8. 学习《深度学习与计算机视觉算法原理框架应用》《大数据架构详解从数据获取到深度学习》PDF代码

    <深度学习与计算机视觉 算法原理.框架应用>全书共13章,分为2篇,第1篇基础知识,第2篇实例精讲.用通俗易懂的文字表达公式背后的原理,实例部分提供了一些工具,很实用. <大数据架构 ...

  9. 2018 NOIP备战计划

    2018 NOIP目标 (1)刷完紫书数论习题 (2)听51nod讲座和习题,根据其知识结构来备战. (3)刷完紫书动规 (4)初赛前两个星期左右开始复习 刷紫书动规的时候感觉偏难,进步缓慢.应该自己 ...

  10. sleep实现原理

    用户程序中的睡眠: sleep()    usleep()    nanosleep() sleep()和nanosleep()都是使进程睡眠一段时间后被唤醒,但是二者的实现完全不同.Linux中并没 ...