1.题目描写叙述:点击打开链接
2.解题思路:本题利用字典树解决。本题要求查找全部的B[j]在A[i]中出现的总次数。那么我们能够建立一颗字典树,将全部的B[j]插入字典树,因为一个串的全部字串相当于它全部后缀的前缀。
因此在查找时候,仅仅须要查找A[i]的每个后缀就可以,然后累加这个后缀的前缀个数,就可以得到该后缀中子串的个数。全部后缀的值相加,就是终于的答案。
3.代码:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <int, int> P; const int N=100000+10; int n,m; char A[N][10005]; char B[N]; struct Trie { int tree[N][26],val[N],cnt; Trie() { init(); } void init() { cnt=1; memset(tree,0,sizeof(tree)); } void insert(char*s) { int p=0,l=strlen(s); for(int i=0;i<l;i++) { int a=s[i]-'a'; if(!tree[p][a]) { val[cnt]=0; tree[p][a]=cnt++; } p=tree[p][a]; } ++val[p]; } int query(char*s) { int p=0,l=strlen(s),ans=0; for(int i=0;i<l;i++) { int a=s[i]-'a'; if(!tree[p][a])return ans; p=tree[p][a]; ans+=val[p]; } return ans; } }T; int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); T.init(); for(int i=0;i<n;i++) scanf("%s",A[i]); ll ans; for(int i=0;i<m;i++) { scanf("%s",B); T.insert(B);//将全部的B[j]插入字典树 } for(int i=0;i<n;i++) { ans=0; int l=strlen(A[i]); for(int j=0;j<l;j++) ans+=T.query(A[i]+j);//枚举后缀的前缀在字典树中出现多少次,得到该后缀的返回值,累加就是答案 printf("%I64d ",ans); } } }