给出长度为n的串,问这个串长度为m的子串有多少个不同的。
这其实是一道SA的裸题,求出height以后,先把长度小于m的后缀删去,然后就这样取,如果一个后缀和前面最后的长度大于等于m的后缀之间的height的最小值小于m,则这个可取。
SA的板子背的还是不够熟啊,又去看了一波biao。
然而这是一道联赛题。
所以hash就好了。
当然单hash被卡了,那就双hash,两个质数,两个模数,用set的pair直接搞一下,挺好打的。
题解用神马斯特林公式算了期望正确率,还挺高的。
Code(SA):
#include
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 2e5 + 5;
int n, m, mm; char a[N];
int tp[N], tax[N], SA[N], rank[N], he[N];
void Rsort() {
fo(i, 1, m) tax[i] = 0;
fo(i, 1, n) tax[rank[tp[i]]] ++;
fo(i, 1, m) tax[i] += tax[i - 1];
fd(i, n, 1) SA[tax[rank[tp[i]]] --] = tp[i];
}
bool cmp(int *f, int x, int y, int c) {return f[x] == f[y] && f[x + c] == f[y + c];}
void Suffix() {
fo(i, 1, n) rank[i] = a[i], tp[i] = i;
m = 128; Rsort();
for(int w = 1, p = 1; p < n; w <<= 1, m = p) {
p = 0; fo(i, n - w + 1, n) tp[++ p] = i;
fo(i, 1, n) if(SA[i] > w) tp[++ p] = SA[i] - w;
Rsort(), swap(rank, tp), rank[SA[1]] = p = 1;
fo(i, 2, n) rank[SA[i]] = cmp(tp, SA[i], SA[i - 1], w) ? p : ++ p;
}
int j = 0, k = 0;
for(int i = 1; i <= n; he[rank[i ++]] = k)
for(k = k ? k - 1 : k, j = SA[rank[i] - 1]; a[i + k] == a[j + k] && max(i, j) + k <= n; k ++);
}
int main() {
freopen("article.in", "r", stdin);
freopen("article.out", "w", stdout);
scanf("%d %d", &n, &mm);
scanf("%s", a + 1);
Suffix();
fo(i, 2, n - 1) if(SA[i] + mm - 1 > n)
he[i + 1] = min(he[i + 1], he[i]);
int fi = 0; int ans = 0;
fo(i, 1, n) if(SA[i] + mm - 1 <= n) {
if(!fi) {
fi = 1;
ans ++;
continue;
}
if(he[i] < mm) ans ++;
}
printf("%d", ans);
}
Code(hash):
#include
#include
#include
#include
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
#define fd(i, x, y) for(ll i = x; i >= y; i --)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const ll N = 2e5 + 5;
ll n, m; char a[N];
const ll p1 = 15312137, p2 = 3113791, mo = 1e9 + 7, mo2 = 1e9 + 9;
ll c[N], d[N];
setint , int> > s;
int main() {
freopen("article.in", "r", stdin);
freopen("article.out", "w", stdout);
scanf("%d %d", &n, &m);
c[0] = 1; fo(i, 1, n) c[i] = c[i - 1] * p1 % mo;
d[0] = 1; fo(i, 1, n) d[i] = d[i - 1] * p2 % mo2;
scanf("%s", a + 1);
ll z = 0, e = 0;
fo(i, 1, m)
z = (z + c[m - i] * a[i] % mo) % mo,
e = (e + d[m - i] * a[i] % mo2) % mo2;
s.insert(make_pair(z, e));
fo(i, m + 1, n) {
z = (z - c[m - 1] * a[i - m] % mo + mo) % mo;
z = z * p1 % mo;
z = (z + a[i]) % mo;
e = (e - d[m - 1] * a[i - m] % mo2 + mo2) % mo2;
e = e * p2 % mo2;
e = (e + a[i]) % mo2;
s.insert(make_pair(z, e));
}
printf("%d", s.size());
}