版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Cymbals/article/details/82716712
题目:https://nanti.jisuanke.com/t/31717
下午打的网络赛,一上来就开了这题,打算秒,结果发现题面没有给字符串长度,最后还是出题人在提问区补的,真的想打人。
后缀自动机裸题,大概就是以下这两题合在一起:
http://hihocoder.com/problemset/problem/1445
http://hihocoder.com/problemset/problem/1449
hihocoder上都有题解。
很裸,求一下endpos,再根据自动机性质,用maxlen(s) - minlen(s) + 1求出当前节点表示多少个子串,最后累加就可以了。
(357队会后缀自动机,这世界真可怕)
ac代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;
char s[maxn];
struct Sam {
int next[maxn << 1][26];
int link[maxn << 1], step[maxn << 1];
ll endpos[maxn << 1];
int a[maxn], b[maxn << 1];
int sz, last, len;
void init() {
memset(next, 0, sizeof(next));
memset(endpos, 0, sizeof(endpos));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
sz = last = 1;
}
void add(int c) {
int p = last;
int np = ++sz;
last = np;
endpos[np] = 1;
step[np] = step[p] + 1;
while(!next[p][c] && p) {
next[p][c] = np;
p = link[p];
}
if(p == 0) {
link[np] = 1;
} else {
int q = next[p][c];
if(step[p] + 1 == step[q]) {
link[np] = q;
} else {
int clone = ++sz;
memcpy(next[clone], next[q], sizeof(next[q]));
step[clone] = step[p] + 1;
link[clone] = link[q];
link[q] = link[np] = clone;
while(next[p][c] == q && p) {
next[p][c] = clone;
p = link[p];
}
}
}
}
void build() {
init();
for(int i = 0; i < len; i++) {
add(s[i] - 'A');
}
for(int i = 1; i <= sz; i++) {
a[step[i]]++;
}
for(int i = 1; i <= len; i++) {
a[i] += a[i - 1];
}
for(int i = 1; i <= sz; i++) {
b[a[step[i]]--] = i;
}
for(int i = sz; i > 1; i--) {
int e = b[i];
endpos[link[e]] += endpos[e];
}
}
void solve() {
int A, B;
scanf("%d%d", &A, &B);
len = strlen(s);
build();
ll ans = 0;
for(int i = 1; i <= sz; i++) {
// printf("%d\n",endpos[i]);
if(endpos[i] >= A && endpos[i] <= B) {
ans += step[i] - step[link[i]];
}
}
printf("%lld\n", ans);
}
} sam;
// AABAA 1 9
int main() {
while(~scanf("%s", s)) {
sam.solve();
}
return 0;
}