POJ 1816 Wild Words

Wild Words
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 4412   Accepted: 1149

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
题目大意:输入N,M然后输入N行字符串,由'?','*'和26个小写字母组成,'?'代表任意一个小写字母,'*'代表0个或者多个小写字母,紧接着输入M行字符串,问每行字符串和前面N行字符串中哪些是等价的。
解题方法:经典的DFS+字典树,先建立建立一颗字典树,然后用DFS进行搜索。
#include <stdio.h>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;

int ans[100005];
int nCount;
char str[25];

typedef struct node
{
    vector <int> id;
    node *next[28];
    node()
    {
        id.clear();
        memset(next, 0, sizeof(next));
    }
    ~node()
    {
        id.clear();
    }
}TreeNode;

int GetIndex(char ch)
{
    switch(ch)
    {
    case '?':
            return 26;
    case '*':
        return 27;
    default:
        return ch - 'a';
    }
}

//建立字典树
void Insert(TreeNode *pRoot, char pstr[], int id)
{
    int nLen = strlen(pstr);
    TreeNode *p = pRoot;
    for (int i = 0; i < nLen; i++)
    {
        int index = GetIndex(pstr[i]);
        if (p->next[index] == NULL)
        {
            p->next[index] = new TreeNode;
        }
        p = p->next[index];
    }
    p->id.push_back(id);//每个单词的结尾保存该单词的编号
}

void DFS(TreeNode *pRoot, int index)
{
    if (pRoot->next[27] != NULL)
    {
        //忽略掉'*',即'*'代表0个字母
        DFS(pRoot->next[27], index);
    }
    if (index == strlen(str))
    {
        //如果遍历到了最后一个字母,则把编号加进去
        for (int i = 0; i < pRoot->id.size(); i++)
        {
            ans[nCount++] = pRoot->id[i];
        }
        return;
    }
    //如果字典树和字符串当前都是字母,则同时跳过该字母
    if (pRoot->next[GetIndex(str[index])] != NULL)
    {
        DFS(pRoot->next[GetIndex(str[index])], index + 1);
    }
    if (pRoot->next[26] != NULL)
    {
        //如果字典树中当前是'?',直接跳过
        DFS(pRoot->next[26], index + 1);
    }
    if (pRoot->next[27] != NULL)
    {
        //如果字典树中当前是‘*’,则让‘*’代表多个字符
        for (int i = index; i < strlen(str); i++)
        {
            DFS(pRoot->next[27], i + 1);
        }
    }
}

void DeleteNode(TreeNode *pRoot)
{
    if (pRoot != NULL)
    {
        for (int i = 0; i < 28; i++)
        {
            DeleteNode(pRoot->next[i]);
        }
    }
    delete pRoot;
}

int main()
{
    int N, M, nID = 0;
    scanf("%d%d", &N, &M);
    TreeNode *pRoot = new TreeNode;
    for (int i = 0; i < N; i++)
    {
        scanf("%s", str);
        Insert(pRoot, str, nID++);
    }
    for (int i = 0; i < M; i++)
    {
        nCount = 0;
        scanf("%s", str);
        DFS(pRoot, 0);
        if (nCount == 0)
        {
            printf("Not match
");
        }
        else
        {
            sort(ans, ans + nCount);
            printf("%d", ans[0]);
            for (int j = 1; j < nCount; j++)
            {
                if (ans[j - 1] != ans[j])
                {
                    printf(" %d", ans[j]);
                }
            }
            printf("
");
        }
    }
    DeleteNode(pRoot);
    return 0;
}
原文地址:https://www.cnblogs.com/lzmfywz/p/3257086.html