http://acm.hdu.edu.cn/showproblem.php?pid=2846

题意:给出N个模式串,再给出M个文本串,问每一个文本串在多少个模式串中出现。

思路:平时都是找前缀的,这里将模式串s[1……len]的每一个[i,len]的子串都插入,这样就可以满足条件。还要注意如果两个子串都为同一个模式串的子串,不能重复计数。可以用一个id数组装上一次是哪个串的id,如果id相同就不要重复计数了。

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define N 2000010
char s[];
struct Trie
{
int ch[N][], num, cnt[N], id[N]; //空间尽量开大点 void init()
{
memset(ch[], , sizeof(ch[]));
num = ;
} void update(char *s, int index)
{
int u = ;
int len = strlen(s);
for(int i = ; i < len; i++) {
int tmp = s[i] - 'a';
if(!ch[u][tmp]) {
memset(ch[num], , sizeof(ch[num]));
cnt[num] = ;
id[num] = ;
ch[u][tmp] = num++;
}
u = ch[u][tmp];
if(id[u] != index) cnt[u]++;
id[u] = index; //标记上一个是否是相同的串,如果相同不能重复计数
}
} int query(char *s)
{
int u = ;
int len = strlen(s);
for(int i = ; i < len; i++) {
int tmp = s[i] - 'a';
if(!ch[u][tmp]) return ;
u = ch[u][tmp];
}
return cnt[u];
}
}trie; int main()
{
int n;
scanf("%d", &n);
trie.init();
for(int i = ; i <= n; i++) {
scanf("%*c%s", s);
int len = strlen(s);
for(int j = ; j < len; j++) {
trie.update(s + j, i); //每一个串的以s[j]开头的子串都要插入
}
}
scanf("%d", &n);
for(int i = ; i < n; i++) {
scanf("%*c%s", s);
printf("%d\n", trie.query(s));
}
return ;
}