標籤:col 簡單 怎麼 很多 ble blank main queue void
傳送門
這道題能想到是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;}
POJ1816 Wild words