/*
TRIE结构,在使用前必须调用初始化init()!!!
主要调用Ins,ser,返回值都是TRIE中的下标;del,返回有无字符串(删除成功否)
*/
#include<stdio.h>
#include<iostream>
#include<memory.h>
#include<queue>
using namespace std;
const int CTNUM = 26; //储存字母的数目
const int STRNUM = 510000; //节点数目,绝对不能少于给定的字符串数目,一般给大点
const int MINCHAR='a'; //大小写分辨,如果混用或者不连续的话需要有对应的hash函数
struct TRIE
{
int son[CTNUM];
int count;
int father;
}trie[STRNUM];
int fail[STRNUM];
int TNUM=1;
queue<int> q;
char s[12000][80],ss[1100000];
int dp[2000][2000],n;
char DNA[4]={'A','C','G','T'};
#define INT_MAX 10000000
void init()
{
memset(&trie[0],0,sizeof(TRIE));
memset(&trie[1],0,sizeof(TRIE));
TNUM=2;
}
int Ins(char *str,int len)
{
int i;
int cur=1;
for(i=0;i<len;i++)
{
if( !trie[cur].son[str[i]-MINCHAR] )
{
memset( &trie[TNUM],0,sizeof(TRIE) );
trie[TNUM].father=cur;
cur=trie[cur].son[str[i]-MINCHAR]=TNUM++;
}
else cur=trie[cur].son[str[i]-MINCHAR];
}
trie[cur].count++;
return cur;
}
void calc_fail()
{
int i,k,p;
fail[0]=0;
fail[1]=0;
memset(fail,0,sizeof(fail));
while(!q.empty()) q.pop();
q.push(1);
while(!q.empty())
{
i=q.front();
q.pop();
// if (trie[fail[i]].count==1)
// trie[i].count=1;
for(k='a'-MINCHAR;k<='z'-MINCHAR;k++)
if (trie[i].son[k]!=0)
{
q.push(trie[i].son[k]);
int p=fail[i];
while(p!=0&&trie[p].son[k]==0)
p=fail[p];
if (!p) fail[trie[i].son[k]]=1;
else
fail[trie[i].son[k]]=trie[p].son[k];
}
}
}
int min(int x,int y)
{
if (x<y) return x;
else return y;
}
int main()
{
int i,j,t,ans,k,u,next,l,st,p;
bool fl;
u=0;
scanf("%d",&n);
while(scanf("%d",&n)!=EOF)
{
if (n==0) break;
// gets(ss);
for(i=1;i<=n;i++)
// gets(s[i]);
scanf("%s",&s[i]);
// gets(ss);
scanf("%s",&ss);
init();
for(i=1;i<=n;i++)
Ins(s[i],strlen(s[i]));
calc_fail();
// calc_tire();
l=strlen(ss);
ans=0;st=1;
for(i=0;i<l;i++)
{
char ch=ss[i];
while((st)&&(trie[st].son[ss[i]-MINCHAR]==0)) st=fail[st];
if (!st) st=1;
else st=trie[st].son[ss[i]-MINCHAR];
p=st;
while(p)
{
ans+=trie[p].count;
trie[p].count=0;
p=fail[p];
}
}
cout<<ans<<endl;
}
}