先对输入的模式串进行处理建树
void insert(string x) { int p=0;//创建根节点 for(int i=0;i<x.size();i++) { int y=x[i]-'0';//对字符进行处理 trie[p][y]=++id; p=trie[p][y];//进入下一层 red[p]++;//储存到该点有多少模板串有此作为前缀 } }
之后对每次询问进行查询
int find(string x) { int p=0; for(int i=0;i<x.size();i++) { int y=x[i]-'0';//处理模板串 if(!trie[p][y])//未开创此条路线,直接结束 return 0; p=trie[p][y];//进入下一层 } return red[p];//返回答案 }
因为是多实例,每次对数组进行手动清空处理(用memset会MLE)
for(int i=0;i<=id;i++) { for(int j=0;j<100;j++) trie[i][j]=0; } for(int i=0;i<=id;i++) red[i]=0; id=0;
AC代码:
#include<bits/stdc++.h> using namespace std; int trie[3000009][100]; int red[3000009]; int id; void insert(string x) { int p=0; for(int i=0;i<x.size();i++) { int y=x[i]-'0'; trie[p][y]=++id; p=trie[p][y]; red[p]++; } } int find(string x) { int p=0; for(int i=0;i<x.size();i++) { int y=x[i]-'0'; if(!trie[p][y]) return 0; p=trie[p][y]; } return red[p]; } int main() { int t; cin>>t; while(t--) { int n,q; cin>>n>>q; for(int i=0;i<=id;i++) { for(int j=0;j<100;j++) trie[i][j]=0; } for(int i=0;i<=id;i++) red[i]=0; id=0; for(int i=0;i<n;i++) { string x; cin>>x; insert(x); } for(int i=0;i<q;i++) { string x; cin>>x; cout<<find(x)<<endl; } } return 0; }