[HDU5769] Substring - 字尾自動機
阿新 • • 發佈:2020-07-13
Description
給你一個串,問你含某個特定的字元的本質不同子串有多少種。
Solution
設 \(f[p]\) 表示從結點 \(p\) 沿著轉移邊走能到達的不同合法子串有多少種
設題中要求要走的字母為 \(c\)
對於 \(p + c \to q\),\(f[p] \leftarrow siz(q)\)
對於 \(p+? \to q, ? \neq c\),\(f[p] \leftarrow f[q]\)
其中 \(siz(p)\) 表示 \(p\) 點往後可以轉移到的本質不同子串數目
#include <bits/stdc++.h> using namespace std; const int N = 200005; struct SAM { int len[N], ch[N][26], fa[N], ind, last; int t[N], a[N], cnt[N], vis[N]; long long f[N]; SAM() { ind = last = 1; } void init() { ind = last = 1; memset(len,0,sizeof len); memset(ch,0,sizeof ch); memset(fa,0,sizeof fa); memset(t,0,sizeof t); memset(a,0,sizeof a); memset(cnt,0,sizeof cnt); memset(f,0,sizeof f); memset(vis,0,sizeof vis); } inline void extend(int id) { int cur = (++ ind), p; len[cur] = len[last] + 1; cnt[cur] = 1; for (p = last; p && !ch[p][id]; p = fa[p]) ch[p][id] = cur; if (!p) fa[cur] = 1; else { int q = ch[p][id]; if (len[q] == len[p] + 1) fa[cur] = q; else { int tmp = (++ ind); len[tmp] = len[p] + 1; for(int i=0; i<26; i++) ch[tmp][i] = ch[q][i]; fa[tmp] = fa[q]; for (; p && ch[p][id] == q; p = fa[p]) ch[p][id] = tmp; fa[cur] = fa[q] = tmp; } } last = cur; } void dfs0(int p,char chr) { vis[p]=1; cnt[p]=1; for(int i=0;i<26;i++) { if(ch[p][i]) { if(!vis[ch[p][i]]) { dfs0(ch[p][i],chr); } cnt[p]+=cnt[ch[p][i]]; } } } void dfs(int p,char chr) { vis[p]=1; for(int i=0;i<26;i++) { if(ch[p][i]) { if(!vis[ch[p][i]]) { dfs(ch[p][i],chr); } if(i==chr-'a') f[p]+=cnt[ch[p][i]]; else f[p]+=f[ch[p][i]]; } } } void solve(char chr) { /*for(int i=ind; i>=1; --i) { for(int j=0; j<26; j++) { if(ch[i][j]) { if(j==chr-'a') f[i]+=cnt[ch[i][j]]; else f[i]+=f[ch[i][j]]; } } }*/ dfs0(1,chr); memset(vis,0,sizeof vis); dfs(1,chr); } } sam; long long solve() { ios::sync_with_stdio(false); string str; char t; cin>>str; t=str[0]; cin>>str; sam.init(); for(int i=0; i<str.length(); i++) sam.extend(str[i]-'a'); sam.solve(t); return sam.f[1]; } signed main() { ios::sync_with_stdio(false); int t; cin>>t; for(int i=1;i<=t;i++) { cout<<"Case #"<<i<<": "<<solve()<<endl; } }