1. 程式人生 > >ACM-ICPC 2018 焦作賽區網路賽 H. String and Times(字尾自動機)

ACM-ICPC 2018 焦作賽區網路賽 H. String and Times(字尾自動機)

下午打的網路賽,一上來就開了這題,打算秒,結果發現題面沒有給字串長度,最後還是出題人在提問區補的,真的想打人。

字尾自動機裸題,大概就是以下這兩題合在一起:

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; }