给定 n 个长度不超过 5050 的由小写英文字母组成的单词,以及一篇长为 m的文章。
请问,其中有多少个单词在文章中出现了。
注意:每个单词不论在文章中出现多少次,仅累计 1 次。
输入格式
第一行包含整数 T,表示共有 T组测试数据。
对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串,表示文章。
输出格式
对于每组数据,输出一个占一行的整数,表示有多少个单词在文章中出现。
数据范围
1≤n≤104,
1≤m≤106输入样例:
1 5 she he say shr her yasherhs
输出样例:
3
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
constexpr int N=10010,S=55,M=10000010;
int n,tr[N*S][26],cnt[N*S],idx;
char str[M];
int q[N*S],ne[N*S];
void insert(){
int p=0;
for(int i=0;str[i];i++){
int t=str[i]-'a';
if(!tr[p][t])tr[p][t]=++idx;
p=tr[p][t];
}
cnt[p]++;
}
void build(){
int hh=0,tt=-1;
for(int i=0;i<26;i++){
if(tr[0][i])
q[++tt]=tr[0][i];
}
while(hh<=tt){
int t=q[hh++];
for(int i=0;i<26;i++){
int c=tr[t][i];
if(!c) continue;
int j=ne[t];
while(j&&!tr[j][i]) j=ne[j];
if(tr[j][i]) j=tr[j][i];
ne[c]=j;
q[++tt]=c;
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(tr,0,sizeof tr);
memset(cnt,0,sizeof cnt);
memset(ne,0,sizeof ne);
idx=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",str);
insert();
}
build();
scanf("%s",str);
int res=0;
for(int i=0,j=0;str[i];i++){
int t=str[i]-'a';
while(j&&!tr[j][t]) j=ne[j];
if(tr[j][t]) j=tr[j][t];
int p=j;
while(p){
res+=cnt[p];
cnt[p]=0;
p=ne[p];
}
}
printf("%d\n",res);
}
return 0;
}
上面的容易被卡 ,下面的防卡
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
constexpr int N=1000010,M=1e6+10;
int n,tr[N][26],cnt[N],idx;
char str[M];
int ne[N];
void insert(){
int p=0;
for(int i=0;str[i];i++){
int t=str[i]-'a';
if(!tr[p][t])tr[p][t]=++idx;
p=tr[p][t];
}
cnt[p]++;
}
void build(){
queue<int> q;
for(int i = 0 ; i < 26 ; ++i){
if(tr[0][i]) q.push(tr[0][i]);
}
while(!q.empty()){
int t = q.front();q.pop();
for(int i = 0 ; i < 26 ; ++i){
int &p = tr[t][i];
if(!p) p = tr[ne[t]][i];
else{
ne[p] = tr[ne[t]][i];
q.push(p);
}
}
}
}
int main(){
idx=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",str);
insert();
}
build();
scanf("%s",str);
int res=0;
for(int i=0,j=0;str[i];i++){
int t = str[i] - 'a';
j = tr[j][t];
int p = j;
while(p and cnt[p] != -1){
res += cnt[p];
cnt[p] = -1;
p = ne[p];
}
}
printf("%d\n",res);
return 0;
}