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)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<set>
 4 const int len(50000),INF(200000);
 5 struct SamNode{int nx[2],pre,step;}sam[len*2+10];
 6 std::set<int>RBT[len*2+10];int size[len*2+10],rt[len*2+10];
 7 std::set<int>::iterator ii,ti;
 8 int top=1,root=1,now=1,last,lastson;
 9 int cnt[len+10],p[len*2+10],mn[len*2+10];
10 void insert(int x)
11 {
12     last=now;now=++top;
13     sam[now].step=sam[last].step+1;
14     size[now]=1;mn[now]=INF;rt[now]=now;
15     RBT[now].insert(sam[now].step);
16     for(;!sam[last].nx[x]&&last;last=sam[last].pre)
17         sam[last].nx[x]=now;
18     if(!last)sam[now].pre=root;
19     else
20     {
21         lastson=sam[last].nx[x];
22         if(sam[lastson].step==sam[last].step+1)sam[now].pre=lastson;
23         else
24         {
25             sam[++top]=sam[lastson];
26             sam[top].step=sam[last].step+1;
27             mn[top]=INF;rt[top]=top;size[top]=0;
28             sam[now].pre=sam[lastson].pre=top;
29             for(;sam[last].nx[x]==lastson&&last;last=sam[last].pre)
30                 sam[last].nx[x]=top;
31         }
32     }
33 }
34 int T,n,ans;char ch[1];
35 void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
36 int min(int a,int b){return a>b?b:a;}
37 int max(int a,int b){return a<b?b:a;}
38 void union_set(int x,int y)
39 {
40     if(size[rt[x]]<size[rt[y]])swap(rt[x],rt[y]);
41     int val;
42     for(ii=RBT[rt[y]].begin();ii!=RBT[rt[y]].end();ii++)
43     {
44         val=*(ii);
45         RBT[rt[x]].insert(val);
46         ti=RBT[rt[x]].find(val);
47         if(ti!=RBT[rt[x]].begin())
48         {
49             ti--;mn[rt[x]]=min(mn[rt[x]],val-*(ti));ti++;
50         }
51         if(ti!=RBT[rt[x]].end())
52         {
53             ti++;
54             if(ti!=RBT[rt[x]].end())mn[rt[x]]=min(mn[rt[x]],*(ti)-val);
55         }
56         size[rt[x]]++;
57     }
58     RBT[rt[y]].clear();
59 }
60 void total()
61 {
62     for(int i=1;i<=n;i++)cnt[i]=0;
63     for(int i=1;i<=top;i++)cnt[sam[i].step]++;
64     for(int i=1;i<=n;i++)cnt[i]+=cnt[i-1];
65     for(int i=top;i>=1;i--)p[cnt[sam[i].step]--]=i;
66     for(int i=top;i>=2;i--)
67     {
68         ans=max(ans,(sam[p[i]].step+mn[rt[p[i]]])/mn[rt[p[i]]]);
69         union_set(sam[p[i]].pre,p[i]);
70     }
71     RBT[rt[1]].clear();
72 }
73 int main()
74 {
75     scanf("%d",&T);
76     while(T--)
77     {
78         memset(sam,0,sizeof(sam));
79         top=1,root=1,now=1;ans=0;
80         mn[1]=INF;rt[1]=1;size[1]=0;
81         scanf("%d",&n);
82         for(int i=1;i<=n;i++)
83         {
84             scanf("%s",ch);
85             insert(ch[0]-'a');
86         }
87         total();
88         printf("%d\n",ans);
89     }
90     return 0;
91 }

转载于:https://www.cnblogs.com/Oncle-Ha/p/6597104.html

Spoj REPEATS 后缀自动机+set相关推荐

  1. SPOJ NSUBSTR(后缀自动机)

    题目链接:http://www.spoj.com/problems/NSUBSTR/ 题目大意:给你一个字符串s(len(s)<=250000),求f[i](i=1...len(s)),其中f[ ...

  2. SPOJ LCS 后缀自动机

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

  3. SPOJ 7258 (后缀自动机)

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

  4. 【后缀自动机】SPOJ 1812-LCSII

    题意: 给出最多10个长度不超过100000的字符串,求他们的LCS的长度.时限是鬼畜的0.25s . 后缀自动机练习...虽然有人这么说但我并不觉得hash能过. 本题可以说是[论SAM中按step ...

  5. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)【两种做法】

    SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)[两种做法] 手动博客搬家: 本文发表于20181217 23:54:35, 原地址https: ...

  6. 【SPOJ】7258. Lexicographical Substring Search(后缀自动机)

    http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一 ...

  7. 【BZOJ2780】【SPOJ】Sevenk Love Oimaster(广义后缀自动机)

    Description 有n个大串和m个询问,每次给出一个字符串s询问在多少个大串中出现过. Solution 广义后缀自动机入门题. 其实就是在插入一个串后将last设为root即可. 然后统计每个 ...

  8. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机、状压DP)

    手动博客搬家: 本文发表于20181217 23:54:35, 原地址https://blog.csdn.net/suncongbo/article/details/85058680 人生第一道后缀自 ...

  9. SPOJ - NSUBSTR Substrings(后缀自动机)

    题目链接:点击查看 题目大意:给出一个字符串,求出每个长度下的子串出现最多的次数 题目分析:对原串跑后缀自动机然后记录每个节点的right集合的大小就是当前节点出现的次数了,这个出现次数显然可以从子节 ...

  10. spoj 1811 LCS 后缀自动机

    A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...

最新文章

  1. 2022-2028年中国TFT玻璃行业市场研究及前瞻分析报告
  2. XCOM串口助手打印不出数据
  3. 两个常数的卷积为多少_卷积(Convolution)与好核函数(Good Kernel)
  4. 并发场景下的幂等问题——分布式锁详解
  5. 停止犯下这5个JavaScript风格错误
  6. WCF中因序列化问题引起的异常和错误。
  7. python3安装步骤-Mac安装python3的方法步骤
  8. contact form 7如何设置placeholder让提示文字显示在输入框中
  9. SPA单页面应用、前后端分离项目SEO优化的方法
  10. Android小项目:计算器
  11. Zoom支持自动生成字幕;SharePlay上线;Safari 更新导致大量bug |WebRTC风向
  12. 与编程密切相关的数学——离散数学——代数系统篇
  13. 白加黑加载方式_基层干部白加黑的工作方式不可取
  14. MATLAB2016笔记(五):进阶矩阵操作
  15. java培训出来的面试经历
  16. Siri的兄弟Viv可能带来下一个人工智能的革命
  17. 2021秋季开学必备数码产品!学生党的超实用好物清单
  18. “33岁转行软件测试还来得及吗?”怎么去转行软件测试?
  19. ChatGPT研究报告:AIGC带来新一轮范式转移
  20. Swagger注解 传参

热门文章

  1. 常用js框架,js库
  2. python整个小服务器
  3. 一个bat文件运行多个java jar包
  4. 推荐一个字体工具:Fontmin
  5. GDAL查看DEM高程数据(java)
  6. Springboot集成Quartz和RabbitMQ时设置为不自动运行
  7. 2015职称计算机考试模拟,2015职称计算机考试《Dreamweaver》模拟试题(9)
  8. linux批量创建ftp用户密码,批量在LINUX下建立很多FTP用户
  9. zk和redis分布式锁比较
  10. 怎样呵护友谊_呵护友谊需要学会尊重对方.PPT