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
思路
字符串的模糊匹配,’?‘可以匹配一个字符,’*'可以匹配一个或者多个字符。题目有几个坑点
- 第一个结尾可能有多个‘*’号。
- 而且有相同重复的模糊串。
最开始的想法是字字典树 + 搜索,字符和问号的情况比较简单就不多说了。因为*号可以匹配一个或者多个,所以搜索的时候当前根节点下跳或者不下跳然后怎么改都不对,看了下题解博客是采用循环的方式控制跳跃字符个数(没想到那么多)。给自己埋个坑,说不定以后哪天想清楚了。
#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;
}
愿你走出半生,归来仍是少年~