Spoj REPEATS 后缀自动机+set
REPEATS - Repeats
链接:http://www.spoj.com/problems/REPEATS
题意:求S串中某个子串连续循环次数最多的次数。
想法:
从暴力开始,枚举所有串,求出这些串的最小循环节长度,算出连续循环次数。
如何求一个串S的最小循环节长度:即next表示这个串最长后缀与前缀相等的长度,最小循环节长度=S.length-next。
KMP可以解决next,于是O(n^2)暴力求出答案。然后优化一下。

上图ans=(len+(x-y))/(x-y)。
在SAM一个节点上,以其{right}为右端点长度为[min,max]的串都相等。那么对应上图,{right}中距离最小的两个点x,y.ans=(max+|x-y|)/|x-y|。
用平衡树维护{right},再启发式合并。
总O(nlog^2n)
#include<cstdio>
#include<cstring>
#include<set>
const int len(),INF();
struct SamNode{int nx[],pre,step;}sam[len*+];
std::set<int>RBT[len*+];int size[len*+],rt[len*+];
std::set<int>::iterator ii,ti;
int top=,root=,now=,last,lastson;
int cnt[len+],p[len*+],mn[len*+];
void insert(int x)
{
last=now;now=++top;
sam[now].step=sam[last].step+;
size[now]=;mn[now]=INF;rt[now]=now;
RBT[now].insert(sam[now].step);
for(;!sam[last].nx[x]&&last;last=sam[last].pre)
sam[last].nx[x]=now;
if(!last)sam[now].pre=root;
else
{
lastson=sam[last].nx[x];
if(sam[lastson].step==sam[last].step+)sam[now].pre=lastson;
else
{
sam[++top]=sam[lastson];
sam[top].step=sam[last].step+;
mn[top]=INF;rt[top]=top;size[top]=;
sam[now].pre=sam[lastson].pre=top;
for(;sam[last].nx[x]==lastson&&last;last=sam[last].pre)
sam[last].nx[x]=top;
}
}
}
int T,n,ans;char ch[];
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
int min(int a,int b){return a>b?b:a;}
int max(int a,int b){return a<b?b:a;}
void union_set(int x,int y)
{
if(size[rt[x]]<size[rt[y]])swap(rt[x],rt[y]);
int val;
for(ii=RBT[rt[y]].begin();ii!=RBT[rt[y]].end();ii++)
{
val=*(ii);
RBT[rt[x]].insert(val);
ti=RBT[rt[x]].find(val);
if(ti!=RBT[rt[x]].begin())
{
ti--;mn[rt[x]]=min(mn[rt[x]],val-*(ti));ti++;
}
if(ti!=RBT[rt[x]].end())
{
ti++;
if(ti!=RBT[rt[x]].end())mn[rt[x]]=min(mn[rt[x]],*(ti)-val);
}
size[rt[x]]++;
}
RBT[rt[y]].clear();
}
void total()
{
for(int i=;i<=n;i++)cnt[i]=;
for(int i=;i<=top;i++)cnt[sam[i].step]++;
for(int i=;i<=n;i++)cnt[i]+=cnt[i-];
for(int i=top;i>=;i--)p[cnt[sam[i].step]--]=i;
for(int i=top;i>=;i--)
{
ans=max(ans,(sam[p[i]].step+mn[rt[p[i]]])/mn[rt[p[i]]]);
union_set(sam[p[i]].pre,p[i]);
}
RBT[rt[]].clear();
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(sam,,sizeof(sam));
top=,root=,now=;ans=;
mn[]=INF;rt[]=;size[]=;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",ch);
insert(ch[]-'a');
}
total();
printf("%d\n",ans);
}
return ;
}
Spoj REPEATS 后缀自动机+set的更多相关文章
- SPOJ NSUBSTR (后缀自动机)
SPOJ NSUBSTR Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数. Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对 ...
- SPOJ LCS 后缀自动机
用后缀自动机求两个长串的最长公共子串,效果拔群.多样例的时候memset要去掉. 解题思路就是跟CLJ的一模一样啦. #pragma warning(disable:4996) #include< ...
- SPOJ - LCS 后缀自动机入门
LCS - Longest Common Substring A string is finite sequence of characters over a non-empty finite set ...
- SPOJ LCS 后缀自动机找最大公共子串
这里用第一个字符串构建完成后缀自动机以后 不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1 如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后 ...
- SPOJ 7258 (后缀自动机)
转载:http://hzwer.com/4492.html 给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 搞出后缀自动机 dp处理出每个点往下走能 ...
- 长度为x的本质不同的串的出现次数 SPOJ - NSUBSTR 后缀自动机简单应用
题意: 长度为x的本质不同的串的出现次数 题解: 先处理出每一个节点所对应的子串出现的次数 然后取max就好了 #include <set> #include <map> #i ...
- 多个串的最长公共子串 SPOJ - LCS2 后缀自动机
题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...
- SPOJ REPEATS 后缀数组
题目链接:http://www.spoj.com/problems/REPEATS/en/ 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现 ...
- SPOJ - SUBLEX 后缀自动机
SPOJ - SUBLEX 思路:求第k大字串,求出sam上每个节点开始能识别多少字串,然后从起点开始跑就好啦. #include<bits/stdc++.h> #define LL lo ...
随机推荐
- Poll: Most Americans&n…
Most Americans support tough new measures to counter gun violence, including banning assault weapons ...
- Elasticsearch之match_phrase小坑记录
1.问题抛出 某个词组在Elasitcsearch中的某个document中存在,就一定通过某种匹配方式把它搜出来. 举例: title=公路局正在治理解放大道路面积水问题. 输入关键词:道路,能否搜 ...
- Celery 基本使用
1. 认识 Celery Celery 是一个 基于 Python 开发的分布式异步消息任务队列,可以实现任务异步处理,制定定时任务等. 异步消息队列:执行异步任务时,会返回一个任务 ID 给你,过一 ...
- Jmeter接口自动化参数化 (转自软件测试部落)
测试场景: 有个查询城市(大概一百个 )天气预报的接口(需求参考第一课),需要根据不同的citycode,去查询对应城市的天气预报,这种接口该如何去测试呢? 分析需求: 不管是功能测试需求,还是接口测 ...
- 自动化测试工具 Test Studio入门教程
Test Studio安装 可以到下载试用版 官网 http://www.telerik.com/teststudio , 装完以后需要装silverlight 安装好了,主界面是介个样子的 Test ...
- 如何在VMware workstation上创建Linux虚拟机
由于需要使用Linux虚拟机部署Hadoop集群,故在win10系统上安装了VMware workstation 14,现将介绍如何在VMware workstation上创建Linux虚拟机.下面以 ...
- python 之 软件开发目录规范 、logging模块
6.4 软件开发目录规范 软件(例如:ATM)目录应该包含: 文件名 存放 备注 bin start.py,用于起动程序 core src.py,程序核心功能代码 conf settings. ...
- 1.函数的结构,调用,传参,形参,实参,args,kwargs,名称空间,高阶函数
1.函数的初识 初始函数 获取任意一个字符串的元素的个数 s1='dsjdkjkfefenga' count=0 for i in s1: count+=1 print(count) 获取列表的元素的 ...
- 初次学习DropWizard框架——解决maven打包时出现没有主清单属性的问题
笔者因为公司的项目需要,开始接触DropWizard框架,照着官网https://www.dropwizard.io/0.9.2/docs/getting-started.html撸了一遍. 工具为I ...
- SVN Trunk Tag Branch
http://blog.csdn.net/vbirdbest/article/details/51122637