1. 程式人生 > >bzoj3172 [Tjoi2013]單詞

bzoj3172 [Tjoi2013]單詞

names ac自動機 closed span bit con bzoj tar targe

傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=3172

【題解】

考慮建出AC自動機,那麽fail樹上每個點的父親為fail,父親->兒子為後綴關系(父親是兒子後綴)

那麽走到父親肯定走到了兒子,直接統計即可。

技術分享
# include <queue>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using
namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1.6e6 + 10; const int mod = 1e9+7; int n; char t[M]; int v[M], ps[M]; vector<int> G[M]; struct ACM { int ch[M][26], fail[M], siz, isend[M]; inline void set() {siz = 0;} inline
int ins(char *t) { int p = 0; for (int i=0; t[i]; ++i) { int c = t[i] - a; if(!ch[p][c]) ch[p][c] = ++siz; p = ch[p][c]; v[p] ++; } return p; } queue<int> q; inline void build() { while(!q.empty()) q.pop();
for (int c=0; c<26; ++c) { int p = ch[0][c]; if(p) { fail[p] = 0; q.push(p); } } while(!q.empty()) { int top = q.front(); q.pop(); for (int c=0; c<26; ++c) { int p = ch[top][c]; if(!p) { ch[top][c] = ch[fail[top]][c]; continue; } q.push(p); int v = fail[top]; while(v && !ch[v][c]) v = fail[v]; fail[p] = ch[v][c]; } } } inline void getfail() { for (int i=1; i<=siz; ++i) G[fail[i]].push_back(i); } }S; inline void dfs(int x) { for (int i=0; i<G[x].size(); ++i) { int y = G[x][i]; dfs(y); v[x] += v[y]; } } int main() { cin >> n; S.set(); for (int i=1; i<=n; ++i) { scanf("%s", t); ps[i] = S.ins(t); } S.build(); S.getfail(); dfs(0); for (int i=1; i<=n; ++i) printf("%d\n", v[ps[i]]); return 0; }
View Code

bzoj3172 [Tjoi2013]單詞