思路:
AC自动机,单词统计。
#include <iostream>
#include <deque>
using namespace std;
const int MAX_NODE = 1000 * 50 + 10;
const int CHILD_NUM = 26;
char virus[1010][56];
int num[1010];
class AcAutomaton
{
private:
int size;
int trie[MAX_NODE][CHILD_NUM];
int value[MAX_NODE];
int fail[MAX_NODE];
int table[128];
public:
void Initialize()
{
fail[0] = 0;
memset(table, -1, sizeof(table));
for (int i = 0; i < 26; ++i)
table['A' + i] = i;
}
void Reset()
{
size = 1;
memset(trie[0], 0, sizeof(trie[0]));
memset(fail, 0, sizeof(fail));
memset(value, 0, sizeof(value));
}
void Insert(char* word, int key)
{
int p = 0;
for (int i = 0; word[i]; ++i)
{
int m = table[word[i]];
if (!trie[p][m])
{
memset(trie[size], 0, sizeof(trie[0]));
trie[p][m] = size++;
}
p = trie[p][m];
}
value[p] = key;
}
void Construct()
{
deque<int> deq;
for (int i = 0; i < CHILD_NUM; ++i)
if (trie[0][i])
{
fail[trie[0][i]] = 0;
deq.push_back(trie[0][i]);
}
while (!deq.empty())
{
int u = deq.front();
deq.pop_front();
for (int i = 0; i < CHILD_NUM; ++i)
{
int& v = trie[u][i];
if (v)
{
fail[v] = trie[fail[u]][i];
deq.push_back(v);
}
else
v = trie[fail[u]][i];
}
}
}
void Work(char* word, int arr[])
{
int p = 0;
for (int i = 0; word[i]; ++i)
{
int m = table[word[i]];
if (m == -1)
{
p = 0; continue;
}
int t = p = trie[p][m];
while (value[t])
{
++arr[value[t]];
t = fail[t];
}
}
}
};
AcAutomaton Ac;
char word[2000010];
int main()
{
int n;
Ac.Initialize();
while (~scanf("%d", &n))
{
Ac.Reset();
for (int i = 1; i <= n; ++i)
{
scanf("%s", virus[i]);
Ac.Insert(virus[i], i);
}
Ac.Construct();
scanf("%s", word);
memset(num, 0, sizeof(num));
Ac.Work(word, num);
for (int i = 1; i <= n; ++i)
if (num[i])
printf("%s: %d\n", virus[i], num[i]);
}
return 0;
}