每次优化的时候标记尽量不一样,那样可以分的清楚一点。
//
// main.cpp
// Richard
//
// Created by 邵金杰 on 16/9/4.
// Copyright © 2016年 邵金杰. All rights reserved.
//
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=2500*1100+100;
const int maxc=5200000+100;
struct node{
node *child[26];
node *pre;
int id;
int key;
void intial(){
memset(child,0,sizeof(child));
pre=NULL;
key=0;
}
}tree[maxn];
char str[maxc],s[2600][1200];
int ncount;
int vis[2600];
int abs(int x)
{
return x>0?x:-x;
}
void Insert(node *p,char *ss,int k)
{
for(;*ss;ss++)
{
int idx=*ss-'A';
if(p->child[idx]==NULL)
{
tree[ncount].intial();
p->child[idx]=tree+ncount;;
ncount++;
}
p=p->child[idx];
}
p->key=1;
p->id=k;
}
void Delete(node *p,char *ss)
{
for(;*ss;ss++)
{
int idx=*ss-'A';
while(p->child[idx]==NULL&&p!=tree+1) p=p->pre;
if(p->child[idx]) p=p->child[idx];
for(node *tmp=p;tmp!=tree+1&&tmp->key!=-3;tmp=tmp->pre)
{
if(abs(tmp->key)==1&&vis[tmp->id])
vis[tmp->id]=0;
tmp->key=-3;
}
}
}
void BuildDFA()
{
for(int i=0;i<26;i++)
tree[0].child[i]=tree+1;
tree[0].pre=NULL;
tree[1].pre=tree;
queue<node*> q;
q.push(tree+1);
while(!q.empty())
{
node *proot=q.front();q.pop();
for(int i=0;i<26;i++)
{
node *p=proot->child[i];
if(p)
{
node *pre=proot->pre;
while(pre)
{
if(pre->child[i]){
p->pre=pre->child[i];
break;
}
else
pre=pre->pre;
}
q.push(p);
}
}
}
}
void Input(int n)
{
for(int i=1;i<=n;i++)
{
char ch;
int len;
int k=0;
scanf("\n");
for(scanf("%c",&ch);ch!='\n';scanf("%c",&ch))
{
if(ch=='[')
{
scanf("%d",&len);
scanf("%c",&ch);
for(int j=0;j<len;j++) s[i][k++]=ch;
scanf("%c",&ch);
}
else
s[i][k++]=ch;
}
s[i][k]='\0';
Insert(tree+1,s[i],i);
}
}
int requery(char *ss)
{
int ans=0;
node *p=tree+1;
for(;*ss;ss++)
{
int idx=*ss-'A';
while(p->child[idx]==NULL&&p!=tree+1) p=p->pre;
if(p->child[idx]) p=p->child[idx];
node *tmp = p;
while(tmp!=tree+1 && tmp->key!=-4)
{
if(abs(tmp->key)==1) ans++;
tmp->key = -4;
tmp = tmp->pre;
}
}
return ans;
}
void Input_artical()
{
char ch;
int len;
int k=0;
scanf("\n");
for(scanf("%c",&ch);ch!='\n';scanf("%c",&ch))
{
if(ch=='[')
{
scanf("%d",&len);
scanf("%c",&ch);
for(int j=0;j<len;j++) str[k++]=ch;
scanf("%c",&ch);
}
else
str[k++]=ch;
}
str[k]='\0';
}
void query(char *ss)
{
node *p=tree+1;
for(;*ss;ss++)
{
int idx=*ss-'A';
while(p->child[idx]==NULL&&p!=tree+1) p=p->pre;
if(p->child[idx]) p=p->child[idx];
node *tmp = p;
while(tmp!=tree+1 && tmp->key>=0)
{
if(tmp->key==1)
{
vis[tmp->id] = 1;
tmp->key = -1;
}
else tmp->key = -2;
tmp = tmp->pre;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ncount=2;
tree[0].intial();
tree[1].intial();
memset(vis,0,sizeof(vis));
int n;
scanf("%d",&n);
Input(n);
Input_artical();
BuildDFA();
query(str);
for(int i=1;i<=n;i++)
{
if(vis[i])
{
Delete(tree+1,s[i]);
Insert(tree+1,s[i],i);
}
}
int ans=requery(str);
cout<<ans<<endl;
}
return 0;
}