POJ1816:Wild Words——题解
http://poj.org/problem?id=1816
比较麻烦的trie。
首先你需要选择针对n还是m建立trie,这里我选择了针对n。
那么就需要面临卡空间的问题。
这里提供了一种链式前向星的方法能够当你不会指针trie的时候卡过空间。(做法看代码吧)
然后针对m进行在trie上的dfs即可。
对于相同字符或?来说,trie下移1位,匹配串移动1位。
对于*来说,trie下移,匹配串移动0~长度位。
(合计这道题就难在模拟上了)
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; const int maxn=600001; char s[21]; struct node{ char se; int to; int nxt; vector<int>ed; }edge[maxn]; int head[maxn],cnt=0,cnt1=1; void add(int u,char c){ cnt++;cnt1++; edge[cnt].se=c; edge[cnt].to=cnt1; edge[cnt].nxt=head[u]; head[u]=cnt; return; } void insert(int k){ int u=1; int l=strlen(s); for(int i=0;i<l;i++){ int v=-1; char c=s[i]; for(int j=head[u];j;j=edge[j].nxt){ if(edge[j].se==c){ v=edge[j].to; if(i==l-1)edge[j].ed.push_back(k); break; } } if(v<0){ add(u,c); v=cnt1; if(i==l-1)edge[cnt].ed.push_back(k); } u=v; } return; } vector<int>ans; int l; void check(int u,int k,int p){ if(k==l){ if(!edge[p].ed.empty()){ for(int i=0;i<edge[p].ed.size();i++){ ans.push_back(edge[p].ed[i]); } } for(int j=head[u];j;j=edge[j].nxt){ int v=edge[j].to; if(edge[j].se=='*'){ check(v,k,j); } } return; } char c=s[k]; for(int j=head[u];j;j=edge[j].nxt){ int v=edge[j].to; if(edge[j].se==c||edge[j].se=='?'){ check(v,k+1,j); } if(edge[j].se=='*'){ for(int q=0;q<=l-k;q++){ check(v,k+q,j); } } } return; } bool t[100001]; int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%s",s); insert(i); } for(int j=0;j<m;j++){ scanf("%s",s); ans.clear(); l=strlen(s); check(1,0,0); if(ans.empty()){ printf("Not match"); }else{ memset(t,0,sizeof(t)); sort(ans.begin(),ans.end()); for(int i=0;i<ans.size();i++){ if(!t[ans[i]]){ printf("%d ",ans[i]); t[ans[i]]=1; } } } printf("\n"); } return 0; }