struct ACauto
{
int next[50010][26],fail[50010],end[50010],root,L;
int Newnode()
{
for ( int i=0 ; i<26 ; i++ )
next[L][i] = -1;
end[L++] = -1;
return L-1;
}
void Init()
{
L = 0; root = Newnode();
}
void Insert( int id , char *s )
{
int len = strlen(s);
int now = root;
for ( int i=0 ; i<len ; i++ )
{
if ( next[now][s[i]-'A']==-1 )
next[now][s[i]-'A'] = Newnode();
now = next[now][s[i]-'A'];
}
end[now] = id;
}
void Build()
{
queue<int>Q; fail[root] = root;
for ( int i=0 ; i<26 ; i++ )
{
if ( next[root][i]==-1 )
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while ( !Q.empty() )
{
int now = Q.front(); Q.pop();
for ( int i=0 ; i<26 ; i++ )
{
if ( next[now][i]==-1 )
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
void Query( char *s )
{
memset ( cnt , 0 , sizeof(cnt) );
int len = strlen(s);
int now = root;
for ( int i=0 ; i<len ; i++ )
{
if ( s[i]>='A'&&s[i]<='Z' )
{
now = next[now][s[i]-'A'];
int tmp = now;
while ( tmp!=root )
{
if ( end[tmp]!=-1 )
cnt[end[tmp]]++;
tmp = fail[tmp];
}
}
else now = root;
}
}
}AC;