新学期新气象,暑假没学什么东西,开学了字符串部分补补姿势。
学习的更多,补题才能有得补,都不会补不动很尴尬。
入门博客自己百度了几发,对着学长给的模板自己写了一下...静态内存省时间。
感觉和KMP差不太多...起码查找都一样。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
char a[1000007];
#define N 1000000
struct Trie
{
int next[N][27],fail[N],mark[N];
int root,L;
int newnode()
{
memset(next[L],-1,sizeof(next[L]));
mark[L]=0;
fail[L++]=-1;
return L-1;
}
void go()
{
L=0;
root=newnode();
}
void init(char *v)
{
int p=root;
for(int i=0;v[i];i++)
{
int tep=v[i]-'a';
if(next[p][tep]==-1) next[p][tep]=newnode();
p=next[p][tep];
}
mark[p]++;
}
void bfs()
{
queue<int>q;
q.push(root);
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(next[p][i]==-1)
{
if(p==root) next[p][i]=root;
else next[p][i]=next[fail[p]][i];
}
else
{
if(p==root) fail[next[p][i]]=root;
else fail[next[p][i]]=next[fail[p]][i];
q.push(next[p][i]);
}
}
}
}
int finde(char *v)
{
int ans=0;
int p=root,q;
for(int i=0;v[i];i++)
{
int tep=v[i]-'a';
while(next[p][tep]==-1&&p!=root)
p=fail[p];
p=next[p][tep];
if(p==-1) p=root;
q=p;
while(q!=root&&mark[q]!=-1)
{
ans+=mark[q];
mark[q]=-1;
q=fail[q];
}
}
return ans;
}
}ac;
int main()
{
int t,n;
scanf("%d",&t);
char v[300];
while(t--)
{
ac.go();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",v);
ac.init(v);
}
scanf("%s",a);
ac.bfs();
printf("%d\n",ac.finde(a));
}
return 0;
}