# 【题解】Tree-String Problem Codeforces 291E AC自动机

### Solution

“这个题好像是某Qualification Round的题啊。。。怎么Qual就出点分治啊，真毒瘤。”

“怎么TLE了，卡卡常。”

“怎么又WA了，难道卡哈希？毒瘤毒瘤。”
debugging。。。
“算了调不出来了拿tourist的代码拍一下吧。”
“这场比赛怎么AK了三百个人啊？这题怎么代码这么短啊？”
“。。。似乎KMP然后dfs一下就没了。。。我简直药丸。。。”

### Code

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;
const int MAXN = 400010;
int _w;

int n, ch[MAXN], m;
char str[MAXN];

namespace G {
void init() {
eid = 0;
}
void adde( int u, int v ) {
}
}

void add_edge( int u, int v, char *str ) {
for( char *p = str; *p; ++p ) {
ch[++m] = *p - 'a';
if( p == str ) G::adde(u, m);
}
}

namespace AC {
int ch[MAXN][26], nid;
bool word[MAXN];
queue<int> q;
int f[MAXN];

void insert( char *s ) {
int u = 0;
for( ; *s; ++s ) {
int c = *s - 'a';
if( !ch[u][c] )
ch[u][c] = ++nid;
u = ch[u][c];
}
word[u] = 1;
}
void build() {
for( int i = 0; i < 26; ++i )
if( ch[0][i] )
q.push( ch[0][i] );
while( !q.empty() ) {
int u = q.front(); q.pop();
for( int i = 0; i < 26; ++i ) {
int v = ch[u][i];
if( !v ) {
ch[u][i] = ch[f[u]][i];
continue;
}
int w = f[u];
while( w && !ch[w][i] ) w = f[w];
f[v] = ch[w][i];
q.push(v);
}
}
}
}

int ans;
void solve( int u, int o ) {
using namespace G;
if( ch[u] != -1 ) {
o = AC::ch[o][ch[u]];
if( AC::word[o] ) ++ans;
}
for( int i = head[u]; ~i; i = nxt[i] )
solve( to[i], o );
}

int main() {
_w = scanf( "%d", &n );
m = n;
G::init();
for( int i = 2; i <= n; ++i ) {
int pa;
_w = scanf( "%d%s", &pa, str );
}