POJ 1816

题意:给出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 }

你可能感兴趣的:(poj)