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:
1
17
b
a
b
b
a
b
a
a
b
a
a
b
a
a
b
a
b
Output:
4
since a (4, 3)-repeat is found starting at the 5th character of the input string.
SPOJ REPEATS Repeats (后缀数组 + RMQ:子串的最大循环节)题解
题意:
给定一个串s,s必有一个最大循环节的连续子串ss,问最大循环次数是多少
思路:
我们可以知道,如果一个长度为L的子串连续出现了两次及以上,那么必然会存在s[0]、s[L]、s[2L]⋯s[L∗k]中至少有两个连续的位置是相同的,然后看字母s[L∗i]和s[L∗(i+1)]往前往后最多能匹配多远,记住总长度len,那么最大循环次数为(len/L)+1。
参考:
SPOJ 687. Repeats(后缀数组)
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119#include<map> #include<set> #include<queue> #include<cmath> #include<stack> #include<ctime> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<sstream> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 50000 + 5; const int INF = 0x3f3f3f3f; const ull seed = 11; const int MOD = 1e9 + 7; using namespace std; //下标从0开始 int str[maxn]; //str[n]赋值一个最小值0,其他大于0 int t1[maxn], t2[maxn], c[maxn]; int sa[maxn]; //排名为i的后缀下标 int rk[maxn]; //后缀下标为i的排名 int height[maxn]; //sa[i]与sa[i - 1]的LCP int mm[maxn]; int dp[maxn][30]; bool cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a + l] == r[b + l]; } void da(int *str, int n, int m){ n++; int i, j, p, *x = t1, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i] = str[i]]++; for(i = 1; i < m; i++) c[i] += c[i - 1]; for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i; for(j = 1; j <= n; j <<= 1){ p = 0; for(i = n - j; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 1; i < m; i++) c[i] += c[i - 1]; for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1 : p++; if(p >= n) break; m = p; } int k = 0; n--; for(i = 0; i <= n; i++) rk[sa[i]] = i; for(i = 0; i < n; i++){ if(k) k--; j = sa[rk[i] - 1]; while(str[i + k] == str[j + k]) k++; height[rk[i]] = k; } } void initRMQ(int n){ mm[0] = -1; for(int i = 1; i <= n; i++){ dp[i][0] = height[i]; mm[i] = ((i & (i - 1)) == 0)? mm[i - 1] + 1 : mm[i - 1]; } for(int j = 1; j <= mm[n]; j++) for(int i = 1; i + (1 << j) - 1 <= n; i++) dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } int RMQ(int L, int R){ int k = mm[R - L + 1]; return min(dp[L][k], dp[R - (1 << k) + 1][k]); } int LCP(int i, int j){ //求后缀i和j的LCP最长公共前缀 int L = rk[i], R = rk[j]; if(L > R) swap(L, R); L++; return RMQ(L, R); } int main(){ int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0; i < n; i++){ char ss[2]; scanf("%s", ss); str[i] = ss[0] - 'a' + 1; } str[n] = 0; da(str, n, 3); initRMQ(n); int ans = 1; for(int i = 1; i < n; i++){ for(int j = 0; j + i < n; j += i){ int len = LCP(j, j + i); int times = len / i + 1; int pos = j - (i - len % i); if(pos >= 0){ len = LCP(pos, pos + i); times = max(times, len / i + 1); } ans = max(ans, times); } } printf("%dn", ans); } return 0; }
最后
以上就是谨慎悟空最近收集整理的关于Repeats SPOJ - REPEATS的全部内容,更多相关Repeats内容请搜索靠谱客的其他文章。
发表评论 取消回复