本题注意模式串匹配不可重复查找
实际上是输出有几种模式串出现在文本串中
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int INF = 0x7FFFFFFF;
const int maxn = 26;
char ss[1000000+maxn];
struct Node
{
Node *next[maxn];
Node *pre;
int last;
Node ()
{
memset(next, 0, sizeof (next));
pre = 0, last = 0;
}
};
Node *root;
void Init ()
{
root = new Node;
}
void Insert (char *s)
{
if (!s[0]) return ;
Node *p = root;
for (int i = 0; s[i]; i++)
{
if (!p -> next[s[i]-'a'])
p -> next[s[i]-'a'] = new Node;
p = p -> next[s[i]-'a'];
}
p -> last++;//记录该节点单词总共插入的次数
}
void Build ()
{
queue <Node*> qu;
for (int i = 0; i < maxn; i++)
if (root -> next[i])
{
root -> next[i] -> pre = root;
qu.push (root -> next[i]);
}
while (!qu.empty ())
{
Node *temp = qu.front (); qu.pop ();
for (int i = 0; i < maxn; i++)
{
Node *pp = temp -> next[i];
if (pp)
{
Node *par = temp -> pre;
do
{
if (par -> next[i])
{
pp -> pre = par -> next[i];
break;
}
else
par = par -> pre;
} while (par);
if (!par)
pp -> pre = root;
qu.push (pp);
}
}
}
}
int Query (char *s)
{
if (!s[0]) return 0;
Node *p = root;
int cnt = 0;
for (int i = 0; s[i]; i++)
{
while (p != root && !p -> next[s[i]-'a'])
p = p -> pre;
p = p -> next[s[i]-'a'];
if (!p)
p = root;
Node *pp = p;
while (pp != root && pp -> last != -1)
{
cnt += pp -> last;
pp -> last = -1;//不可重复查找
pp = pp -> pre;
}
}
return cnt;
}
void DelTree (Node *s)
{
if (!s) return ;
for (int i = 0; i < maxn; i++)
{
if (s -> next[i])
DelTree (s -> next[i]);
}
delete s;
}
int main()
{
int t;
scanf ("%d", &t);
while (t--)
{
int n;
scanf ("%d",&n);
Init ();
for (int i = 1; i <= n; i++)
{
scanf ("%s", ss);
Insert (ss);
}
getchar();
gets (ss);
Build ();
printf ("%d\n", Query (ss));
DelTree (root);
}
return 0;
}
1
2
aa
bb
aacdaacd
1