这道题能想到是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(' ') 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 "); 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; }