ACM-ICPC 2018 焦作賽區網路賽 H. String and Times(字尾自動機)
阿新 • • 發佈:2018-12-10
下午打的網路賽,一上來就開了這題,打算秒,結果發現題面沒有給字串長度,最後還是出題人在提問區補的,真的想打人。
字尾自動機裸題,大概就是以下這兩題合在一起:
hihocoder上都有題解。
很裸,求一下endpos,再根據自動機性質,用maxlen(s) - minlen(s) + 1求出當前right集合裡有多少個子串就可以了。
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 << 1], b[maxn << 1];
int sz, last, len;
void init() {
memset(next, 0, sizeof(next));
memset(endpos, 0, sizeof(endpos));
memset(link , 0, sizeof(link));
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;
}