POJ1816(Wild Words)

Wild Words

Description

A word is a string of lowercases. A word pattern is a string of lowercases, '?'s and ‘'s. In a pattern, a ‘?’ matches any single lowercase, and a '’ matches none or more lowercases.

There are many word patterns and some words in your hand. For each word, your task is to tell which patterns match it.
Input

The first line of input contains two integers N (0 < N <= 100000) and M (0 < M <=100), representing the number of word patterns and the number of words. Each of the following N lines contains a word pattern, assuming all the patterns are numbered from 0 to N-1. After those, each of the last M lines contains a word.

You can assume that the length of patterns will not exceed 6, and the length of words will not exceed 20.
Output

For each word, print a line contains the numbers of matched patterns by increasing order. Each number is followed by a single blank. If there is no pattern that can match the word, print “Not match”.
Sample Input

5 4
t*
?hs
??e

*s
?*e
this
the
an
is
Sample Output

0 1 3
0 2 4
Not match

3

思路

字符串的模糊匹配,’?‘可以匹配一個字符,’*'可以匹配一個或者多個字符。題目有幾個坑點

  1. 第一個結尾可能有多個‘*’號。
  2. 而且有相同重複的模糊串。
    最開始的想法是字字典樹 + 搜索,字符和問號的情況比較簡單就不多說了。因爲*號可以匹配一個或者多個,所以搜索的時候當前根節點下跳或者不下跳然後怎麼改都不對,看了下題解博客是採用循環的方式控制跳躍字符個數(沒想到那麼多)。給自己埋個坑,說不定以後哪天想清楚了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;
const int maxn = 100050;
int trie[maxn][28];
bool f[maxn],vis[maxn];
int num[maxn];	
char s[25];
int cnt;
void insert_s(char *s,int index)
{
	int root = 0;
	int n = strlen(s),k;
	for(int i = 0;i < n;i++){
		if(s[i] == '?')		k = 26;			//匹配單個字符 
		else if(s[i] == '*')		k = 27;		//匹配多個 
		else	k = s[i] - 'a';
		if(!trie[root][k]){
			trie[root][k] = ++cnt;
		}
		root = trie[root][k];
	}
	f[root] = true;
	num[index] = root;
}
void find_s(int st,int ed,int root)
{
	if(st > ed)		return ;
	if(st == ed && f[root]){
		vis[root] = true;
		//這裏不能回溯,因爲結尾可能有多個***。
	}
	if(trie[root][s[st]-'a']){
		find_s(st+1,ed,trie[root][s[st]-'a']);
	}
	if(trie[root][26]){
		find_s(st+1,ed,trie[root][26]);
	} 
	if(trie[root][27]){
		for(int i = st;i <= ed;i++){
			find_s(i,ed,trie[root][27]);
		}
//		find_s(st+1,ed,root);			//理論上這種方法也沒錯,可能就只能是理論AC吧。
//		find_s(st+1,ed,trie[root][27]);
	}
}
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		memset(f,false,sizeof(f));
		memset(num,0,sizeof(f));
		memset(trie,0,sizeof(trie));
		cnt = 0;
		for(int i = 0;i < n;i++){
			scanf("%s",s);
			insert_s(s,i);
		}
		for(int i = 0;i < m;i++){
			scanf("%s",s);
			memset(vis,false,sizeof(vis));
			int slen = strlen(s);
			find_s(0,slen,0);
			int ans = 0;
			for(int j = 0;j < n;j++){
				if(vis[num[j]]){
					if(ans){
						printf(" %d",j);
					}
					else{
						printf("%d",j);
					}
					ans++;
				}
			}
			if(!ans)	printf("Not match");
			printf("\n");
		}
	}
	return 0;
}

願你走出半生,歸來仍是少年~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章