HUST 1352 Repetitions of Substrings

来源:互联网 发布:如何在淘宝店发通告 编辑:程序博客网 时间:2024/06/08 09:59

Description

The “repetitions” of a string S(whose length is n) is a maximum number “k” such that: 1) k is a factor of n 2) S[0..n/k-1] = S[p*(n/k)..(p+1)*(n/k)-1] for all that (1 <= p < n/k) for example: the repetitions of “aaaaaa”is 6. the repetitions of “abababab”is 4. the repetitions of “abcdef”is 1. Now, given a string S and a number K, please tell me how many substrings of S have repetitions NOT less than K.

Input

The input consists of several instances, each one for a single line. S K S is a string, K is a number. Check the Description for their meanings. S contains lowercase letters(ie 'a'..'z') only. 1 <= length of S <= 100000. 1 <= K <= length of S.

Output

For each instance, output the number of substring whose repetitions is NOT less than K.

Sample Input

abcabc 2acmac 3

Sample Output

1

0

判断有多少子串满足循环至少k次,用后缀数组,计算出height

然后循环对于每个位置判断可能的最大长度,除k,得到循环节的可能长度,分别枚举每个循环节判断。

这题数据很水,让很多有问题的程序跑过了,错误点见注释。

#include<set>#include<map>#include<ctime>#include<cmath>#include<stack>#include<queue>#include<bitset>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>#include<functional>#define rep(i,j,k) for (int i = j; i <= k; i++)#define per(i,j,k) for (int i = j; i >= k; i--)#define lson x << 1, l, mid#define rson x << 1 | 1, mid + 1, r#define fi first#define se second#define mp(i,j) make_pair(i,j)#define pii pair<int,int>using namespace std;typedef long long LL;const int low(int x) { return x&-x; }const double eps = 1e-8;const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e5 + 10;const int read(){char ch = getchar();while (ch<'0' || ch>'9') ch = getchar();int x = ch - '0';while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';return x;}int m;struct Sa{char s[N];int rk[2][N], sa[N], h[N], w[N], now, n;int rmq[N][20], lg[N], f[N];bool GetS(){return scanf("%s%d", s + 1, &m) != EOF;}void getsa(int z, int &m){int x = now, y = now ^= 1;rep(i, 1, z) 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;rep(i, 1, m) w[i] = 0;rep(i, 1, n) w[rk[x][rk[y][i]]]++;rep(i, 1, m) w[i] += w[i - 1];per(i, n, 1) 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){rk[1][0] = now = sa[0] = s[0] = 0;n = strlen(s + 1);rep(i, 1, m) w[i] = 0;rep(i, 1, n) w[s[i]]++;rep(i, 1, m) rk[1][i] = rk[1][i - 1] + (bool)w[i];rep(i, 1, m) w[i] += w[i - 1];rep(i, 1, n) rk[0][i] = rk[1][s[i]];rep(i, 1, n) sa[w[s[i]]--] = i;rk[1][n + 1] = rk[0][n + 1] = 0;//多组的时候容易出bugfor (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-- : 0)while (rk[now][i] - 1 && s[sa[rk[now][i] - 1] + j] == s[i + j]) ++j;}void getrmq(){h[n + 1] = h[1] = lg[1] = 0;rep(i, 2, n) rmq[i][0] = h[i], lg[i] = lg[i >> 1] + 1;for (int i = 1; (1 << i) <= n; i++){rep(j, 2, n){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(255);if (m == 1){printf("%lld\n", 1LL * n * (n + 1) / 2);return;}getrmq();LL ans = 0;rep(i, 1, n) f[i] = 0;rep(i, 1, n){int t = max(h[i], h[i + 1]) / (m - 1);rep(L, 1, t){if (sa[i] + L > n) break;if (f[L] == i) continue;int R = lcp(sa[i], sa[i] + L);if (R / L  + 2 >  m) ans += R / L + 2 - m;rep(k, 1, R / L) f[k*L] = i;/*if (R >= L) break;这里有毒,加上这句话可以快很多的AC,然而这是错的,看了很多人的程序,都是这么写的。明显的样例是 aabaab 2    正确答案是 3 而加上这句话会输出 2 明显是不对的,只能说数据很水。*/}}printf("%lld\n", ans);}}sa;int main(){while (sa.GetS()) sa.work();return 0;}


0 0
原创粉丝点击