/*
http://acm.pku.edu.cn/JudgeOnline/problem?id=1816
trie树下的DFS, 感觉非常好的一道题,能说明很多问题
*/
#include <iostream>
#include <algorithm>
#define MAX_M 100000
using namespace std;
//输入的pattern数以及待匹配的单词数
int pNum, strNum;
char temp[30];
//当前单词匹配的模式ID以及匹配的模式数
int match[MAX_M + 1], matchNum = 0;
//类似于邻接表,当有两个模式串巷同时进行记录和匹配
struct pN
{
//模式串的ID
int id;
//邻接模式串
pN *next;
};
//用于对匹配的模式串ID进行排序
bool compare(int a, int b)
{
if(a >= b)
return true;
}
//得到当前字符c在trie树next表中的index下标
int getIndex(char c)
{
int pos = 0;
if(c == '?') pos = 26;
else if(c == '*') pos = 27;
else pos = c - 'a';
return pos;
}
//trie树节点的定义
struct trieNode
{
int id;
//0-25表示a-z 26个小写字母,26表示'?',27表示'*'
trieNode *next[28];
pN *rep; //记录重复的pattern
trieNode()
{
//初始化
for(int i = 0; i < 28; i++)
next[i] = NULL;
id = 0;
rep = NULL;
}
};
//trie树的根
trieNode *root;
//向trie树中插入模式串pattern, id为id
void insert(char pattern[], int id)
{
char c;
int i, pos, len = strlen(pattern);
if(!root) root = new trieNode();
trieNode *curNode = root;
for(i = 0; i < len; i++)
{
c = pattern[i];
pos = getIndex(c);
if(!curNode->next[pos])
curNode->next[pos] = new trieNode();
curNode = curNode->next[pos];
}
//记录ID,如果已经出现过此匹配串则需要添加邻接信息
if(curNode->id == 0)
curNode->id = id;
else
{
pN *newPN = new pN();
newPN->id = id;
newPN->next = curNode->rep;
curNode->rep = newPN;
}
}
//待匹配单词为temp,当前匹配到的位置是pos,当前匹配到的结点是curNode
void trieDFS(char * const & temp, int pos, trieNode *curNode)
{
//当整个单词扫描完,不能立即返回,因为单词后面还可以接*号
if(pos >= strlen(temp))
{
//当前结点是一个有效的模式串
if(curNode->id != 0)
{
//标记匹配信息
match[matchNum++] = curNode->id;
pN *rpn = curNode->rep;
while(rpn)
{
match[matchNum++] = rpn->id;
rpn = rpn->next;
}
}
}
//若当前单词还没有扫描完,则继续扫描
if(pos < strlen(temp))
{
char c;
c = temp[pos];
//直接匹配当前字母
int index = getIndex(c);
if(curNode->next[index])
trieDFS(temp, pos + 1, curNode->next[index]);
//匹配?
if(curNode->next[26])
trieDFS(temp, pos + 1, curNode->next[26]);
}
//匹配*
if(curNode->next[27])
{
int p;
for(p = pos; p <= strlen(temp); p++)
trieDFS(temp, p, curNode->next[27]);
}
}
int main()
{
int i, j;
cin>>pNum>>strNum;
for(i = 0; i < pNum; i++)
{
scanf("%s", temp);
insert(temp, i + 1);
}
for(i = 0; i < strNum; i++)
{
cin>>temp;
matchNum = 0;
trieDFS(temp, 0, root);
if(matchNum == 0)
printf("Not match/n");
else
{
sort(match, match + matchNum);
for(j = 0; j < matchNum - 1; j++)
{
if(match[j] != match[j + 1])
printf("%d ", match[j] - 1);
}
printf("%d/n", match[matchNum - 1] - 1);
}
}
return 0;
}