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 ...
随机推荐
- 《精通Spring4.X企业应用开发实战》读后感第三章
- Centos7 安装vim8
一.卸载旧版本的vim yum -y remove vim* 二.安装终端字符处理库ncurses yum -y install ncurses-devel 三.下载Vim8 wget https:/ ...
- HDU - 1869 六度分离 Floyd多源最短路
六度分离 1967年,美国著名的社会学家斯坦利·米尔格兰姆提出了一个名为“小世界现象(small world phenomenon)”的著名假说,大意是说,任何2个素不相识的人中间最多只隔着6个人,即 ...
- Java8函数式接口之Predicate<T>
作用: 这是一个功能接口,因此可以作为lambda表达式或方法引用的赋值目标. 实例: /** * Created by luo on 2017/5/3. */ public class Predic ...
- Java 普通方法和构造方法的区别
构造方法: ①方法名和 类名相同 ②在方法名的前面没有返回值类型的声明 ③在方法中不能使用return语句返回一个值 ④在创建对象时,要调用new,如:book b1=new book(); ⑤当没有 ...
- Lightoj1059【最小生成树】
题意: 使得所有的位置都能通向一个机场,问最小花费. 思路: 最小生成树. 本来还想标记一下没有出现过的点,其实那个数组已经解决了.==. PS:注意路比建造机场还贵?直接造机场得了? if ther ...
- Hyperledger Fabric (1.0)环境部署 chaincode【转】
三.测试Fabric 其实我们在前面运行./network_setup.sh up的时候系统已经运行了一个Example02的ChainCode测试,部署上去的ChainCodeName是mycc,所 ...
- 洛谷P4003 无限之环(费用流)
传送门 神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦 到底是得有怎样的脑回路才能一眼看去就是费用流啊…… 建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图 首先, ...
- Python学习笔记(异常处理)
用户输入了一个不合规定的值,或者需要打开的文件不存在.这些情况被称作“异常”,一个好的程序需要能处理可能发生的异常,避免程序因此而中断. 例如我们去打开一个文件: f = file('non-exis ...
- C# IE环境 - 重置IE(WshShell & Rundll32)
前言 IE问题: 如何重置IE选项? 通过修改注册表,理论上是可行的.前提是你知道重置IE时,有多少注册表项要更改. 如果能直接调用IE的重置设置窗口,并执行重置,能完美重置IE. WshShell ...