poj 1816 Wild Words (字符串_字典树)

题目链接: http://poj.org/problem?id=1816

题目大意:给定n个模式串,模式串中带有?和*,?可以当作任何一个字符,*可以当作随意个字符,也可以是0个。现在给出m个匹配串,问哪些模式串出现在当个匹配串中,按照这些模式串编号的字典序输出。
 
解题思路:用字典树+DFS求解.利用n个模式串建棵字典树,字典树节点保存next指针和当前所在的节点编号,对每个节点编号,为什么是保存节点编号而不是按照常规的方法保存是否为字符串尾呢?因为模式串可能会重复,所以需要另外开个vector保存,这样就可以通过对应的节点编号找到重复模式串的数量。然后就是查询,用每个串去遍历字典树,碰到?也要往下走,碰到“*”则判断匹配串的后面若干个字符是否在模式串中出现,还需要判断下一个是不是“*”,如果符合就往后遍历。在这个过程要判重,每个模式串只会出现一个,还需要按字典序,答案排个序就好。


测试数据:
5 1
jjjj
jjjj
jjj
jkjkj
kjkjk
jjjj

5 4
t*
?h*s
??e*
*s
?*e
the
this
an
is

5 4
****
????
***
tttt
*?*?
abcd
tttt
fuck

what


代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX 110000


vector<int> cnt[MAX*7];
struct node {


	int pos;
	node *next[28];
}*root;
int vis[MAX],nodenum;
int n,m,ans[MAX],tot;
char pa[30],word[30];




int hash(char c) {


	if (c == '?')
		return 26;
	else if (c == '*')
		return 27;
	else return c - 'a';
}
node *CreateNode() {


	node *p;
	p = (node *) malloc (sizeof(node));
	p->pos = ++nodenum;
	for (int i = 0; i < 28; ++i)
		p->next[i] = NULL;
	return p;
}
void Release(node *p) {


	for (int i = 0; i < 28; ++i)
		if (p->next[i] != NULL) Release(p->next[i]);
	cnt[p->pos].clear();
	free(p);
}
void Insert(char *str,int in) {


	int i = 0,k;
	node *p = root;




	while (str[i]) {


		k = hash(str[i++]);
		if (p->next[k] == NULL)
			p->next[k] = CreateNode();
		p = p->next[k];
	}
	cnt[p->pos].push_back(in);
//	printf("p->pos = %d num = %d\n",p->pos,cnt[p->pos].size());
}
void Query(char *str,node *p) { //str是将要匹配的字符串,p是父节点


	int i,j,tp;
	if (str[0] == '\0') {
	//word已匹配到最后
		if (cnt[p->pos].size() != 0) {
			
			tp = cnt[p->pos].size();
			for (j = 0; j < tp; ++j)
				if (vis[cnt[p->pos][j]] == 0)
					ans[++tot] = cnt[p->pos][j],vis[cnt[p->pos][j]] = 1;
		}
		while (p->next[27] != NULL) {
			
			if (cnt[p->next[27]->pos].size() != 0) {
				
				tp = cnt[p->next[27]->pos].size();
				for (j = 0; j < tp; ++j)
					if (vis[cnt[p->next[27]->pos][j]] == 0)
						ans[++tot] = cnt[p->next[27]->pos][j],vis[cnt[p->next[27]->pos][j]] = 1;
			}
			p = p->next[27];
		}
		return;
	}




	int k = hash(str[0]);
	if (p->next[k] != NULL) Query(str+1,p->next[k]);
	if (p->next[26] != NULL) Query(str+1,p->next[26]);
	if (p->next[27] != NULL) {


		if (p->next[27]->next[27] != NULL) Query(str,p->next[27]);
		for (i = 0; str[i]; ++i) {
			
			int index = hash(str[i]);
			if (p->next[27]->next[index] != NULL )
				Query(str+i+1,p->next[27]->next[index]);
			if (p->next[27]->next[26] != NULL)
				Query(str+i+1,p->next[27]->next[26]);
		}
		Query(str+i,p->next[27]);
	}
}






int main()
{
	int i,j,k;




	while (scanf("%d%d",&n,&m) != EOF) {


		nodenum = 0;
		root = CreateNode();
		for (i = 0; i < n; ++i)
			scanf("%s",pa),Insert(pa,i);
		for (i = 0; i < m; ++i) {


			tot = 0;
			memset(vis,0,sizeof(vis));
			scanf("%s",word);
			Query(word,root);
			sort(ans+1,ans+1+tot);
			if (tot == 0)
				printf("Not match\n");
			else for (j = 1; j <= tot; ++j)
				printf(j == tot ? "%d \n" : "%d ",ans[j]);
		}
		Release(root);
	}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

你可能感兴趣的:(vector,struct,测试,null,query,insert)