POJ1816 Wild words

传送门

这道题能想到是trie树+搜索,不过在trie树上dfs确实让人大开眼界……

具体怎么做呢?首先我们可以按照模式串来建立一棵trie树,不过这样的话空间限制是一个问题。解决的方法是把trie树像建图一样用链式前向星去存储,这样的话就节省了很多空间(具体怎么实现可以看代码,还是很简单的)。之后我们把这棵trie树建好,之后就得开始搜了……其实普通的点和?都很可以,不过遇到*号的话,我们就要枚举长度去向下搜索。我们记录一下当前枚举到第几位,当前的节点和当前的边,然后普通的点我们把k+1,如果遇到*的话就要枚举所有可能的长度去深搜。

还有此题有坑……*是可以为空的,所以我们需要在搜到最后特判一下这种情况,继续搜。

然后,这道题还有重复的模式串……解决的方法是在每个点再开一个vector来记录一下有哪些重复的串。

看一下代码吧。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
#define pb push_back
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')

using namespace std;
typedef long long ll;
const int M = 40005;
const int N = 600005;
const ll mod = 1000000007;

int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
    if(ch == '-') op = -1;
    ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
    ans *= 10;
    ans += ch - '0';
    ch = getchar();
    }
    return ans * op;
}

struct edge
{
    char ch;
    int next,to;
    vector<int> ed;
}e[N];

int head[N],ecnt,cnt = 1,n,m;
char s[25];

void add(int x,char c)
{
    e[++ecnt].to = ++cnt;
    e[ecnt].ch = c;
    e[ecnt].next = head[x];
    head[x] = ecnt;
}

void insert(int k)
{
    int u = 1,l = strlen(s);
    rep(i,0,l-1)
    {
    int v = -1;
    char c = s[i];
    for(int j = head[u];j;j = e[j].next)
    {
        if(e[j].ch == c)
        {
        v = e[j].to;
        if(i == l-1) e[j].ed.pb(k);
        break;
        }
    }
    if(v < 0)
    {
        add(u,c),v = cnt;
        if(i == l-1) e[ecnt].ed.pb(k);
    }
    u = v;
    }
}

vector <int> ans;
int len;

void check(int u,int k,int p)
{
    if(k == len)
    {
    if(!e[p].ed.empty()) rep(i,0,e[p].ed.size()-1) ans.pb(e[p].ed[i]);
    for(int j = head[u];j;j = e[j].next) if(e[j].ch == '*') check(e[j].to,k,j);
    return;
    }
    char c = s[k];
    for(int j = head[u];j;j = e[j].next)
    {
    if(e[j].ch == c || e[j].ch == '?') check(e[j].to,k+1,j);
    if(e[j].ch == '*') rep(q,0,len-k) check(e[j].to,k+q,j);
    }
}

bool vis[100001];

int main()
{
    n = read(),m = read();
    rep(i,0,n-1) scanf("%s",s),insert(i);
    rep(j,0,m-1)
    {
    scanf("%s",s),ans.clear(),len = strlen(s);
    check(1,0,0);
    if(ans.empty()) printf("Not match\n");
    else
    {
        memset(vis,0,sizeof(vis));
        sort(ans.begin(),ans.end());
        rep(i,0,ans.size()-1) if(!vis[ans[i]]) printf("%d ",ans[i]),vis[ans[i]] = 1;
        enter;
    }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/captain1/p/9770041.html