SUBST1 - New Distinct Substrings
Given a string, we need to find the total number of its distinct substrings.
Input
T- number of test cases. T<=20; Each test case consists of one string, whose length is <= 50000
Output
For each test case output one number saying the number of distinct substrings.
Example
Input: 2 CCCCC ABABA Output: 5 9
题意:给定一个字符串,求不同子串的数目
解题思路:后缀数组
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
const int N = 200010;
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];
void GetS()
{
scanf("%s", s + 1);
n = strlen(s + 1);
}
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;
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);
int ans = n + 1 - sa[1];
for (int i = 2; i <= n; i++)
{
if (h[i] <= 0) ans += n + 1 - sa[i];
else ans += n + 1 - sa[i] - h[i];
}
printf("%d\n", ans);
}
}sa;
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
sa.GetS();
sa.work();
}
return 0;
}