多串匹配,AC自动机。
设置一个vis数组记录匹配成功防止多次匹配同一模式串。
用三叉树杭电oj内存1400+K,用时800+ms,所谓的空间换时间了。
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
using namespace std;
const int maxn = 100010;
int Node[maxn][3], link[maxn], fail[maxn];
char elem[maxn];
int vis[550];
int top, ans;
queue <int> que;
int newNode(char ch)
{
top ++;
Node[top][0] = Node[top][1] = Node[top][2] = 0;
link[top] = 0;
elem[top] = ch;
return top;
}
void Insert(char str[], int id)
{
int p = 1, idx = 0;
while(str[idx])
{
if(!Node[p][2]) Node[p][2] = newNode(str[idx]);
p = Node[p][2];
while(elem[p] != str[idx])
{
if(str[idx] < elem[p])
{
if(!Node[p][0]) Node[p][0] = newNode(str[idx]);
p = Node[p][0];
}
else
{
if(!Node[p][1]) Node[p][1] = newNode(str[idx]);
p = Node[p][1];
}
}
idx ++;
}
link[p] = id;
}
int findNext(int fp, int p)
{
while(elem[fp] != elem[p])
{
if(elem[p] < elem[fp])
if(!Node[fp][0]) return 0;
else fp = Node[fp][0];
else
if(!Node[fp][1]) return 0;
else fp = Node[fp][1];
}
fail[p] = fp;
return 1;
}
int q[140], tl, hd;
void travelPre(int p, int pre)
{
tl = hd = 0;
q[++hd] = p;
while(tl < hd)
{
p = q[++tl];
que.push(p);
int tmp = fail[pre];
while(tmp && !findNext(Node[tmp][2], p)) tmp = fail[tmp];
if(tmp == 0) fail[p] = 1;
if(Node[p][0]) q[++hd] = Node[p][0];
if(Node[p][1]) q[++hd] = Node[p][1];
}
}
void getFail()
{
int p = 1;
while(!que.empty()) que.pop();
que.push(p);
fail[1] = 0;
while(!que.empty())
{
p = que.front();
que.pop();
if(Node[p][2])
travelPre(Node[p][2], p);
}
}
int matchCH(char ch, int p, int &pre)
{
while(ch != elem[p])
{
if(ch < elem[p])
if(!Node[p][0]) return 0;
else p = Node[p][0];
else
if(!Node[p][1]) return 0;
else p = Node[p][1];
}
pre = p;
while(p && !vis[link[p]])
{
if(link[p])
{
ans ++;
vis[link[p]] = 1;
}
p = fail[p];
}
return 1;
}
void match(char str[])
{
int idx = 0;
int p = 1;
while(str[idx])
{
while(p && !matchCH(str[idx], Node[p][2], p)) p = fail[p];
if(p == 0) p = 1;
idx ++;
}
}
int main()
{
int n, m, i;
scanf("%d",&n);
char str[10010];
top = 0;
newNode('\0');
for(i = 1; i <= n; i++)
{
scanf("%s",str);
Insert(str, i);
}
getFail();
scanf("%d",&m);
int total = 0;
for(i = 1; i <= m; i++)
{
ans = 0;
memset(vis, 0, sizeof(vis));
scanf("%s", str);
match(str);
if(ans)
{
total ++;
printf("web %d:", i);
for(int j = 1; j <= n; j++)
if(vis[j]) printf(" %d", j);
printf("\n");
}
}
printf("total: %d\n",total);
return 0;
}