hihocoder 1260 String Problem I (Trie树 好题)

来源:互联网 发布:苹果time capsule知乎 编辑:程序博客网 时间:2024/04/30 07:15
时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

我们有一个字符串集合S,其中有N个两两不同的字符串。

还有M个询问,每个询问给出一个字符串w,求有多少S中的字符串可以由w添加恰好一个字母得到。

字母可以添加在包括开头结尾在内的任意位置,比如在"abc"中添加"x",就可能得到"xabc", "axbc", "abxc", "abcx".这4种串。

输入

第一行两个数N和M,表示集合S中字符串的数量和询问的数量。

接下来N行,其中第i行给出S中第i个字符串。

接下来M行,其中第i行给出第i个询问串。

所有字符串只由小写字母构成。

数据范围:

N,M<=10000。

S中字符串长度和<=100000。

所有询问中字符串长度和<=100000。

输出

对每个询问输出一个数表示答案。

样例输入
3 3touristpetrrngtoosimplergptr
样例输出
011

题目链接:http://hihocoder.com/problemset/problem/1260

题目分析:感觉正解不是Trie但是还是用Trie搞过了,其实就是在trie树上DFS的时候有一个点可以“失配”而直接跳到下一层,Search(char *s, int pos, int p, bool ok),s表示要查询的字符串,pos表示枚举到s的第pos位,p表示当前父亲编号,ok表示之前是否已经跳过一次,true表示没跳过,这里有个问题就是比如

2 1
aa
ab
a

错误答案跑出来会是3,因为对于aa来说,他先跳和后跳的情况都被计算了,因此还需要记录一个单词是否已经满足情况,由于点的个数太多但是n比较小,所以考虑将单词结尾标号用map离散化,还有一点要注意的就是当pos==len的时候不能直接return,因为有可能在最后一个单词那里跳,比如

1 1

ab

b

所以当pos==len时要先判断跳不跳,再return

#include <cstdio>#include <cstring>#include <algorithm>#include <map>using namespace std;int const MAX = 1e5 + 5;int n, m, ans, len;char s[MAX];struct Trie{int next[MAX * 26][26], end[MAX * 26], tot, root, num;bool vis[10005];map <int, int> mp;inline int Newnode(){memset(next[tot], -1, sizeof(next[tot]));end[tot] = false;return tot ++;} inline void Init(){num = 0;tot = 0;root = Newnode();}inline void Insert(char *s){int p = root;for(int i = 0; i < (int)strlen(s); i++){int idx = s[i] - 'a';if(next[p][idx] == -1)next[p][idx] = Newnode();p = next[p][idx];}end[p] = true;mp[p] = num ++;}inline void Search(char *s, int pos, int p, bool ok){if(end[p] && !vis[mp[p]] && pos == len){vis[mp[p]] = true;ans ++;return;}if(ok)for(int i = 0; i < 26; i++)if(next[p][i] != -1)Search(s, pos, next[p][i], false);if(pos == len)return;int idx = s[pos] - 'a';if(next[p][idx] != -1)Search(s, pos + 1, next[p][idx], ok);}}t;int main(){t.Init();scanf("%d %d",&n, &m);for(int i = 0; i < n; i++){scanf("%s", s);t.Insert(s);}for(int i = 0; i < m; i++){scanf("%s", s);ans = 0;len = strlen(s);memset(t.vis, false, sizeof(t.vis));t.Search(s, 0, t.root, true);printf("%d\n", ans);}}

0 0
原创粉丝点击