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的更多相关文章

  1. SPOJ NSUBSTR (后缀自动机)

    SPOJ NSUBSTR Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数. Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对 ...

  2. SPOJ LCS 后缀自动机

    用后缀自动机求两个长串的最长公共子串,效果拔群.多样例的时候memset要去掉. 解题思路就是跟CLJ的一模一样啦. #pragma warning(disable:4996) #include< ...

  3. SPOJ - LCS 后缀自动机入门

    LCS - Longest Common Substring A string is finite sequence of characters over a non-empty finite set ...

  4. SPOJ LCS 后缀自动机找最大公共子串

    这里用第一个字符串构建完成后缀自动机以后 不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1 如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后 ...

  5. SPOJ 7258 (后缀自动机)

    转载:http://hzwer.com/4492.html 给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 搞出后缀自动机 dp处理出每个点往下走能 ...

  6. 长度为x的本质不同的串的出现次数 SPOJ - NSUBSTR 后缀自动机简单应用

    题意: 长度为x的本质不同的串的出现次数 题解: 先处理出每一个节点所对应的子串出现的次数 然后取max就好了 #include <set> #include <map> #i ...

  7. 多个串的最长公共子串 SPOJ - LCS2 后缀自动机

    题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...

  8. SPOJ REPEATS 后缀数组

    题目链接:http://www.spoj.com/problems/REPEATS/en/ 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现 ...

  9. SPOJ - SUBLEX 后缀自动机

    SPOJ - SUBLEX 思路:求第k大字串,求出sam上每个节点开始能识别多少字串,然后从起点开始跑就好啦. #include<bits/stdc++.h> #define LL lo ...

随机推荐

  1. django根据不同app配置相应的log文件

    django根据不同app配置相应的log文件 settings.py # django logging LOG_PATH = "/var/log/blog/" LOGGING = ...

  2. JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API

    森林森 一份耕耘,一份收获 博客园 首页 新随笔 联系 管理 订阅 随笔- 397  文章- 0  评论- 78  JAVA基础学习day16--集合三-Map.HashMap,TreeMap与常用A ...

  3. MVC 中dapper的日志功能+程序报错修改

    由于之前的项目说最好要有日志功能,正好之前看过几篇这方面的文章就弄了点东西. 这是EF日志受启发很大的一个原文: http://www.cnblogs.com/GuZhenYin/p/5556732. ...

  4. Git 分支管理 BUG分支

    BUG分支  廖雪峰 软件开发中,bug就像家常便饭一样.有了bug就需要修复, 在Git中,由于分支是如此的强大,所以, 每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支 ...

  5. 2014-9-13 NOIP模拟赛

    NOIP2014模拟赛 ——lwher 题目名 环上的游戏 舞蹈课 数位和乘积 源文件 cycle.cpp/c/pas dancingLessons.pas/cpp digit.cpp.cpp/c/p ...

  6. 基于react+如何搭建一个完整的前端框架(1)

      1.使用 create-react-app 快速构建 React 开发环境 create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境. ...

  7. iOS 根据文字字数动态确定Label宽高

    iOS7中用以下方法 - (CGSize)sizeWithAttributes:(NSDictionary *)attrs; 替代过时的iOS6中的- (CGSize)sizeWithFont:(UI ...

  8. java基础第七篇之接口

    1.什么是接口: * 接口是方法的集合,而且接口中的方法全是抽象的 * 你可以把接口看成一个特殊的"抽象类",接口中的方法全是抽象的 * * * 2.java中怎么定义接口: * ...

  9. CCPC吉林站

    A.The Fool #include <bits/stdc++.h> using namespace std; inline int read() { ,f=;char ch=getch ...

  10. PAT甲级——1112 Stucked Keyboard (字符串+stl)

    此文章同步发布在我的CSDN上:https://blog.csdn.net/weixin_44385565/article/details/90041078   1112 Stucked Keyboa ...