标签:else 开始 表示 mem void 模板 code ext 数列
(刷的第一道后缀自动机)
正式开始后缀自动机的漫长道路
hihoCoder 1145
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。
现在小Hi想知道一部作品中出现了多少不同的旋律?
共一行,包含一个由小写字母构成的字符串。字符串长度不超过 1000000。
一行一个整数,表示答案。
aab
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5;; char s[maxn]; struct Sam { int next[maxn << 1][26]; int link[maxn << 1], step[maxn << 1];//step int a[maxn], b[maxn << 1]; int sz, last, root; void init() { //如多次建立自动机,加入memset操作 root = sz = last = 1; } void add(int c) { int p = last; int np = ++sz; last = np; step[np] = step[p] + 1; while(!next[p][c] && p) { next[p][c] = np; p = link[p]; } if(p == 0) { link[np] = root; } else { int q = next[p][c]; if(step[p] + 1 == step[q]) { link[np] = q; } else { int nq = ++sz; memcpy(next[nq], next[q], sizeof(next[q])); step[nq] = step[p] + 1; link[nq] = link[q]; link[q] = link[np] = nq; while(next[p][c] == q && p) { next[p][c] = nq; p = link[p]; } } } } void build() { init(); for(int i = 0; s[i]; i++) { add(s[i] - ‘a‘); } for(int i = 1; i <= sz; i++) { a[step[i]]++; } for(int i = 1; i <= step[last]; i++) { a[i] += a[i - 1]; } for(int i = 1; i <= sz; i++) { b[a[step[i]]--] = i; } } } sam; int main() { cin>>s; long long ans = 0; sam.build(); for(int i = 1;i<=sam.sz;i++) { ans+=sam.step[i]-sam.step[sam.link[i]]; // cout<<ans<<" += "<<sam.step[i]<<" - "<<sam.step[sam.link[i]]<<endl; } cout<<ans<<endl; }
标签:else 开始 表示 mem void 模板 code ext 数列
原文地址:https://www.cnblogs.com/kgs719/p/9853692.html