SPOJREPEATS-Repeats
来源:互联网 发布:asc软件 编辑:程序博客网 时间:2024/06/06 01:53
REPEATS - Repeats
A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string
s = abaabaabaaba
is a (4,3)-repeat with t = aba as its seed string. That is, the seed string t is 3 characters long, and the whole string s is obtained by repeating t 4 times.
Write a program for the following task: Your program is given a long string u consisting of characters ‘a’ and/or ‘b’ as input. Your program must find some (k,l)-repeat that occurs as substring within u with k as large as possible. For example, the input string
u = babbabaabaabaabab
contains the underlined (4,3)-repeat s starting at position 5. Since u contains no other contiguous substring with more than 4 repeats, your program must output the maximum k.
Input
In the first line of the input contains H- the number of test cases (H <= 20). H test cases follow. First line of each test cases is n - length of the input string (n <= 50000), The next n lines contain the input string, one character (either ‘a’ or ‘b’) per line, in order.
Output
For each test cases, you should write exactly one interger k in a line - the repeat count that is maximized.
Example
Input:117babbabaabaabaababOutput:4since a (4, 3)-repeat is found starting at the 5th character of the input string.
题意:给定一个字符串,求重复次数最多的连续重复子串的重复次数
解题思路:首先连续出现1次是肯定可以的,所以这里只考虑至少2次的情况。当枚举到合适的子串长度时,在枚举r[L*i]和r[L*(i+1)]的过程中,必然可以出现r[L*i]在第一个循环节里,而r[L*(i+1)]在第二个循环节里的这种情况,如果此时r[L*i]是第一个循环节的首字符,这样直接用公共前缀k除以i并向下取整就可以得到最后结果。但如果r[L*i]如果不是首字符,这样算完之后结果就有可能偏小,因为r[L*i]前面可能还有少许字符也能看作是第一个循环节里的。先算出从r[L*i]开始,除匹配了k/i个循环节,还剩余了几个字符,剩余的自然是k%i个字符。如果说r[L*i]的前面还有i-k%i个字符完成比配的话,这样就相当于还可以再匹配出一个循环节,所以只要检查一下从r[L*i-(i-k%i)]和r[L*i-(i-k%i)+i]开始是否有i-k%i个字符能够完成匹配即可,也就是检查这两个后缀的最长公共前缀是否比i-k%i大即可
#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <stack>#include <queue>#include <vector>#include <map>using namespace std;const int N=200010;const int INF=0x7FFFFFFF;struct Sa{ char s[N]; int rk[2][N],sa[N],h[N],w[N],now,n; int rmq[N][20],lg[N],bel[N]; bool GetS() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%s",s+i); return true; } void getsa(int z,int &m) { int x=now,y=now^=1; for(int i=1; i<=z; i++) rk[y][i]=n-i+1; for(int i=1,j=z; i<=n; i++) if(sa[i]>z) rk[y][++j]=sa[i]-z; for(int i=1; i<=m; i++) w[i]=0; for(int i=1; i<=n; i++) w[rk[x][rk[y][i]]]++; for(int i=1; i<=m; i++) w[i]+=w[i-1]; for(int i=n; i>=1; i--) sa[w[rk[x][rk[y][i]]]--]=rk[y][i]; for(int i=m=1; i<=n; i++) { int *a=rk[x]+sa[i],*b=rk[x]+sa[i-1]; rk[y][sa[i]]=*a==*b&&*(a+z)==*(b+z)?m-1:m++; } } void getsa(int m) { now=rk[1][0]=sa[0]=s[0]=0; n=strlen(s+1); for(int i=1; i<=m; i++) w[i]=0; for(int i=1; i<=n; i++) w[s[i]]++; for(int i=1; i<=m; i++) rk[1][i]=rk[1][i-1]+(bool)w[i]; for(int i=1; i<=m; i++) w[i]+=w[i-1]; for(int i=1; i<=n; i++) rk[0][i]=rk[1][s[i]]; for(int i=1; i<=n; i++) sa[w[s[i]]--]=i; rk[1][n+1]=rk[0][n+1]=0; for(int x=1,y=rk[1][m]; x<=n&&y<=n; x<<=1) getsa(x,y); for(int i=1,j=0; i<=n; h[rk[now][i++]]=j?j--:j) { if(rk[now][i]==1) continue; int k=n-max(sa[rk[now][i]-1],i); while(j<=k&&s[sa[rk[now][i]-1]+j]==s[i+j]) ++j; } } void getrmq() { h[n+1]=h[1]=lg[1]=0; for(int i=2; i<=n; i++) rmq[i][0]=h[i],lg[i]=lg[i>>1]+1; for(int i=1; (1<<i)<=n; i++) { for(int j=2; j<=n; j++) { if(j+(1<<i)>n+1) break; rmq[j][i]=min(rmq[j][i-1],rmq[j+(1<<i-1)][i-1]); } } } int lcp(int x,int y) { int l=min(rk[now][x],rk[now][y])+1,r=max(rk[now][x],rk[now][y]); return min(rmq[l][lg[r-l+1]],rmq[r-(1<<lg[r-l+1])+1][lg[r-l+1]]); } void work() { getsa(300); getrmq(); int ans=1; for(int L=1;L<=n;L++) { for(int i=1;i+L<=n;i+=L) { int R=lcp(i,i+L); ans=max(ans,R/L+1); if(i>L-R%L) ans=max(lcp(i-L+R%L,i+R%L)/L+1,ans); } } printf("%d\n",ans); }}sa;int main(){ int t; scanf("%d",&t); while(t--) { sa.GetS(); sa.work(); } return 0;}
- SPOJREPEATS-Repeats
- multiple repeats
- spoj687. Repeats
- spoj687 REPEATS
- spoj687 Repeats
- Repeats SPOJ
- SPOJ687---REPEATS - Repeats(后缀数组+RMQ)
- spoj687 REPEATS - Repeats (后缀数组+rmq)
- [SPOJ687]REPEATS - Repeats(后缀数组+st)
- spoj 687. Repeats
- SPOJ REPEATS SA
- 【后缀数组】SPOJ REPEATS
- SPOJ REPEATS(后缀数组)
- [FFC]no-repeats-please
- spoj 687 repeats
- JS:No Repeats Please
- No repeats please
- SPOJ REPEATS 后缀数组
- 二叉树线索化
- Android 代码混淆语法讲解及常用模板
- OpenCV学习笔记(一)——Linux下的OpenCV配置
- “实现模拟三次密码输入”的场景的c程序
- 剑指offer第19题(顺时针打印矩阵)
- SPOJREPEATS-Repeats
- 明确问题,加以解决。
- Linux 基础学习篇1
- Mybatis学习笔记-关联表查询的问题 (一对多关联)
- hibernate注解关联
- android 7.1.1下android.permission.SYSTEM_ALERT_WINDOW改动及BUG
- u32 u16 s32 s16 u8 s8是什么
- vue.js 下拉刷新插件(demo)
- 实例讲解虚拟机3种网络模式(桥接、nat、Host-only)