pku 1816 wild words trie树的活用

pku 1816 wild words trie树的活用

题意:
模板包括3种字符:
a-z:标准字符
通配符?,代表任意一个字符
*:代表0个或多个字符

先给出n个模板串,m个字符串,问每个字符串分别匹配那几个模板串
n<=1e6,m<=1e2,strlen<20

解法:
用trie树构建模板串,然后再dfs来匹配
应为模板串中有重复串,一个简单的方法是,开辟一个链表空间,链接每个模板串的末节点
然后判断每个字符串时DFS一次,将能到达的尾部节点做个标记,然后根据之前记录的链表扫一遍就知道到达过哪些模板串的根节点(匹配了哪些模板串)
DFS的时候要注意下几点:
1、状态设定:(节点编号、当前字符串位置)
2、如果当前节点中存在'?"的转移路径,则转移过去
3、如果当前节点存在'*'的转移路径,枚举*匹配的长度,然后转移
总复杂度1e7左右。。。不知道有什么好的方法,我的程序C++跑了400MS。。。不算快的。。

另外,这题建议用动态内存分配,我开始开了100W的buffer,竟然MLE。。。。
代码:
 1 # include  < cstdio >
 2 # include  < cstring >
 3 # include  < cstdlib >
 4
 5 using   namespace  std;
 6 struct  node
 7 {
 8    node *nxt[28];
 9    bool in;
10    node()
11    {
12          memset(nxt,NULL,sizeof(nxt));
13          in=false;
14    }

15}
* ans[ 100005 ],head;
16 char  map[ 255 ];
17 int  c = 1 ;
18 node *  insert( char   * str)
19 {
20   node *p=&head;
21   for(int i=0;str[i]!='\0';i++)
22   {
23      if(p->nxt[map[str[i]]]==NULL)
24         p->nxt[map[str[i]]]=new node();
25      p=p->nxt[map[str[i]]];
26   }

27   return p;
28}

29 void  match(node  * p, char   * str)
30 {
31     if(!p) return;
32     if(*str=='\0')
33     {
34        p->in=true;
35        match(p->nxt[27],str);
36     }

37     else
38     {
39         match(p->nxt[map[*str]],str+1);
40         match(p->nxt[26],str+1);
41         for(int i=0;i<=strlen(str);i++)
42           match(p->nxt[27],str+i);
43     }

44}

45 int  main()
46 {
47    int n,m;
48    for(int i='a';i<='z';i++)
49       map[i]=i-'a';
50    map['?']=26;
51    map['*']=27;
52    scanf("%d%d",&n,&m);
53    for(int i=0;i<n;i++)
54    {
55       char str[10];
56       scanf("%s",str);
57       ans[i]=insert(str);
58    }

59    for(int i=0;i<m;i++)
60    {
61        for(int j=0;j<n;j++) ans[j]->in=false;
62        char str[128];
63        scanf("%s",str);
64        match(&head,str);
65        bool flag=false;
66        for(int j=0;j<n;j++)
67          if(ans[j]->in)
68           {
69              flag=true;
70              printf("%d ",j);
71           }

72        if(flag) printf("\n");
73        else printf("Not match\n");
74    }

75  // system("pause");
76    return 0;
77}

78

你可能感兴趣的:(pku 1816 wild words trie树的活用)