题意:给出n个模式串,串中除开小写字母外,?代表一个字符,*代表可空的任意字符串,然后再给出m个字符串,问有多少个模式串可以与之匹配。

题解:通过模式串建立字典树,接着就是用字符串去dfs就行了,需要注意的就是遇到当前节点为*则还可以继续走当前结点,由于每次dfs要么字典树匹配深度加1,要么字符串位置加1,所以不会出现死循环。另外这题有些卡内存,模式串可能一样,记录每个结点代表哪些模式串时可以参照图论建边的方法,建一个邻接表储存各个结点的模式串信息。

View Code
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<set>
  5 #include<vector>
  6 using namespace std;
  7 const int N=100005;
  8 struct node
  9 {
 10     char ch;
 11     int next[30];
 12     void init(char _ch)
 13     {
 14         ch=_ch;
 15         memset(next,-1,sizeof(next));
 16     }
 17 }tr[N*10];
 18 int cnt,head[N],nc;
 19 bool mark[N];
 20 struct Edge
 21 {
 22     int to,next;
 23 }edge[N*2];
 24 void add(int a,int b)
 25 {
 26     edge[nc].to=b;edge[nc].next=head[a];head[a]=nc++;
 27 }
 28 inline int change(char x)
 29 {
 30     if(x=='?')
 31         return 26;
 32     else if(x=='*')
 33         return 27;
 34     else
 35         return x-'a';
 36 }
 37 void insert(char s[],int id)
 38 {
 39     int i,p;
 40     for(i=0,p=0;s[i]!='\0';i++)
 41     {
 42         int pt=change(s[i]);
 43         if(tr[p].next[pt]==-1)
 44         {
 45             tr[p].next[pt]=cnt;
 46             p=cnt++;
 47             tr[p].init(s[i]);
 48         }
 49         else
 50             p=tr[p].next[pt];
 51     }
 52     add(p,id);
 53 }
 54 bool flag;
 55 void dfs(char s[],int p)
 56 {
 57     if(s[0]=='\0')
 58     {
 59         for(int i=head[p];i!=-1;i=edge[i].next)
 60             flag=mark[edge[i].to]=true;
 61         if(tr[p].next[27]!=-1)
 62             dfs(s,tr[p].next[27]);
 63         return;
 64     }
 65     int pt=change(s[0]);
 66     if(tr[p].next[pt]!=-1)
 67         dfs(s+1,tr[p].next[pt]);
 68     if(tr[p].next[26]!=-1)
 69         dfs(s+1,tr[p].next[26]);
 70     if(tr[p].next[27]!=-1)
 71         dfs(s+1,tr[p].next[27]),dfs(s,tr[p].next[27]);
 72     if(tr[p].ch=='*')
 73         dfs(s+1,p);
 74 }
 75 int main()
 76 {
 77     int n,m;
 78     while(scanf("%d%d",&n,&m)!=EOF)
 79     {
 80         tr[0].init('$');
 81         cnt=1;
 82         memset(head,-1,sizeof(head));
 83         nc=0;
 84         for(int i=0;i<n;i++)
 85         {
 86             char s[30];
 87             scanf("%s",s);
 88             insert(s,i);
 89         }
 90         while(m--)
 91         {
 92             char s[30];
 93             scanf("%s",s);
 94             flag=false;
 95             memset(mark,false,sizeof(mark));
 96             dfs(s,0);
 97             if(!flag)
 98             {
 99                 printf("Not match\n");
100                 continue;
101             }
102             for(int i=0;i<n;i++)
103             {
104                 if(mark[i])
105                 {
106                     if(flag)
107                         flag=false;
108                     else
109                         printf(" ");
110                     printf("%d",i);
111                 }
112             }
113             printf("\n");
114         }
115     }
116     return 0;
117 }