poj1816 Wild Words

Wild Words
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 5567   Accepted: 1475

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*
?h*s
??e*
*s
?*e
this
the
an
is

Sample Output

0 1 3 
0 2 4 
Not match
3

Source

大致题意:给n个模式串和m个字符串,*可以代表任意字符串(空串),?只能代表一个特定字符,问每个字符串有哪些模式串与它匹配?
分析:题目给了很多模式串,将它们放在trie树上.因为可能会有相同的模式串,所以需要记录一下当前点为多少个模式串的终点,利用vector或者邻接表都可以.匹配的话利用dfs,一个指针在trie上走,另一个在字符串上走,每次匹配有3种可能:1.直接走当前字符的下一位. 2.走?的一位. 3.走*的一位.对于?和*,用特殊的数字26,27存在trie中.*的转移比较麻烦,它有可能只占一个字符,有可能是空串,也有可能占很多串,这样就要分三种情况搜下去.对于第三种情况,由于trie存的是边,并不知道当前点是不是由*转移过来的,必须要在trie树中表示每个点的字符.需要注意的是搜索的终点并不是字符串的完结,而是trie跳到了终点,因为可能模式串末尾有一大堆**这么一说非常抽象,看代码可能更容易理解一些.
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>

const int maxn = 100001;

using namespace std;
int n, m, len, tot = 1, head[maxn], nextt[maxn], to[maxn], tott = 1;
char s[maxn], s2[maxn];
bool flag[maxn], can;

vector <int> E[maxn];

struct node
{
    char ch;
    int tr[30];
    void clear(char c)
    {
        ch = c;
        memset(tr, 0, sizeof(tr));
    }
}e[maxn * 10];

int zhuanhuan(char x)
{
    if (x == '?')
        return 26;
    if (x == '*')
        return 27;
    else
        return x - 'a';
}

void add(int x, int y)
{
    to[tott] = y;
    nextt[tott] = head[x];
    head[x] = tott++;
}

void insert(char *ss, int id)
{
    int u = 1;
    len = strlen(ss + 1);
    for (int i = 1; i <= len; i++)
    {
        int t = zhuanhuan(ss[i]);
        if (!e[u].tr[t])
        {
            e[u].tr[t] = ++tot;
            e[tot].clear(ss[i]);
        }
        u = e[u].tr[t];
    }
    add(u, id); //邻接表
}

void dfs(int dep, int u)
{
    if (dep == len + 1)
    {
        for (int i = head[u]; i; i = nextt[i])
        {
            int v = to[i];
            can = flag[v] = 1;
        }
        if (e[u].tr[27])   //trie没走完
            dfs(dep, e[u].tr[27]);
        return;
    }
    int temp = zhuanhuan(s2[dep]);
    if (e[u].tr[temp])
        dfs(dep + 1, e[u].tr[temp]);
    if (e[u].tr[26])
        dfs(dep + 1, e[u].tr[26]);
    if (e[u].tr[27])
    {
        dfs(dep + 1, e[u].tr[27]);
        dfs(dep, e[u].tr[27]);
    }
    if (e[u].ch == '*') //如果当前点是*
        dfs(dep + 1, u);
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%s", s + 1);
        insert(s, i - 1);
    }
    while (m--)
    {
        can = false;
        scanf("%s", s2 + 1);
        len = strlen(s2 + 1);
        memset(flag, false, sizeof(flag));
        dfs(1, 1);
        if (!can)
        {
            printf("Not match\n");
            continue;
        }
        for (int i = 0; i < n; i++)
            if (flag[i])
                printf("%d ", i);
        printf("\n");
    }

    return 0;
}

 

posted @ 2017-12-17 09:55  zbtrs  阅读(303)  评论(0编辑  收藏  举报