题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846
题目:输入个n个词典串,然后输入q个串,对这q个串分别输出每个串都是几个词典串的子串。
思路:因为要包含子串,比如abd,将串abd,bd,d都插入字典树,然后每个节点下统计子树个数,直接查找前缀就可以了。但需要注意dcda这种的,需要插入dcda,cda,da,a,这个时候d下面的子树应该是一个而不是2个,因为dcda和da属于同一个词典串。所以在插入的时候进行处理即可。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ceil(x, y) (((x) + (y) - 1) / (y))
const int SIZE = 30;
const int N = 3e6 + 10;
const int M = 1e3 + 10;
const int INF = 0x7f7f7f7f;
const int MAX_WORD = 1e2 + 10;
const double EPS = 1e-9;
const int MOD = 2015;
int sz;
int ch[N][SIZE];
int val[N];
int id[N];
char str[MAX_WORD];
char txt[MAX_WORD];
int newnode() {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
id[sz] = 0;
return sz++;
}
void init() {
sz = 0;
newnode();
}
void insert(char *s, int st, int j) {
int u = 0;
for (int i = st; s[i]; i++) {
int v = s[i] - 'a';
if (!ch[u][v])
ch[u][v] = newnode();
u = ch[u][v];
if (id[u] != j)
val[u]++;
id[u] = j;
}
}
int find(char *s) {
int u = 0;
for (int i = 0; s[i]; i++) {
int v = s[i] - 'a';
if (!ch[u][v])
return 0;
u = ch[u][v];
}
return val[u];
}
int main() {
int p, q;
while (scanf("%d", &p) != EOF) {
init();
for (int i = 1; i <= p; i++) {
scanf("%s", str);
int len = strlen(str);
for (int j = 0; j < len; j++)
insert(str, j, i);
}
scanf("%d", &q);
for (int i = 0; i < q; i++) {
scanf("%s", txt);
printf("%d\n", find(txt));
}
}
return 0;
}