需要对于每一个字符串,要把它本身和他的所有后缀都放进字典树里,这样才能在后面的查询中查询到子串。
加入把一个"abab"的字符串加入,然后查询‘a’,会返回2,这显然是错误的,所以我们对于字典树中的每个结点应该加一个num属性,来记录最后更新该节点的字符串的序号,如果这次本次更新和上次更新的字符串的序号相同,即这次更新的是之前某次字符串的后缀,那么就不再增加次数。
数组的范围按照描述设为200010的话不知道为什么不行,调成1000000就好了。
#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <queue>
#include <map>
#define N 1000010
using namespace std;
const int INF = 0x3f3f3f3f;
int t,q;
struct Node{
Node* ch[26];
int num,sum;
}a[N],*root;
int p = 0;
Node* newNode(){
p++;
memset(a[p].ch,0,sizeof(a[p].ch));
a[p].sum = 1;
a[p].num = 0;
return &a[p];
}
void insert(char s[],int num0){ //num0表示字符串的序号
Node* cur = root;
while (*s != '\0')
{
int x = *s-'a';
if(cur->ch[x] == NULL){
cur->ch[x] = newNode();
cur = cur->ch[x];//转移之后直接更改sum等
cur->sum = 1;
cur->num = num0;
}else{
cur = cur->ch[x];
}
if(cur->num != num0){ //如果本次使用的字符串不是之前某次的后缀
cur->sum++;
cur->num = num0;
}
s++;
}
}
int find(char s[]){
Node* cur = root;
while (*s != '\0')
{
int x = *s-'a';
if(cur->ch[x] == NULL){
return 0;
}
cur = cur->ch[x];
s++;
}
return cur->sum;
}
int main(){
int i,j,k;
root = newNode();
scanf("%d",&t);
char s[25];
for(i=1;i<=t;i++){
scanf("%s",s);
int len = strlen(s);
for(int j = 0;j<len;j++){
insert(s+j,i); //把所有后缀放进去,用i表示字符串的序号
}
}
scanf("%d",&q);
for(i=1;i<=q;i++){
scanf("%s",s);
printf("%d\n",find(s));
}
return 0;
}