这题关键还是时间问题HDU上时间卡的是2000ms,POJ卡1000ms,所以最终要的是优化。
优化主要在查找,一开始写的是用危险结点来判断要不要走,这样的话只要是危险结点都要走,就算这个点之前走过,也不会停下来。后来用count来判断,如果count为-1,那就不用走了,因为以前肯定走过了,而且路径是一样的,所以节省了大量时间。
//
// main.cpp
// Richard
//
// Created by 邵金杰 on 16/8/31.
// Copyright © 2016年 邵金杰. All rights reserved.
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1000+10;
const int maxn=5100000+100;
const int maxv=250*1000+100;
struct node{
node *child[26];
node *pre;
int count;
void intial(){
memset(child,0,sizeof(child));
pre=NULL;
count=0;
}
}tree[maxv];
char s[N],str[maxn],su[maxn];
int ncount;
int size;
void Insert(node *p)
{
int len=(int)strlen(s);
for(int i=0;i<len;i++)
{
if(p->child[s[i]-'A']==NULL)
{
p->child[s[i]-'A']=tree+ncount;
ncount++;
}
p=p->child[s[i]-'A'];
}
p->count++;
}
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()
{
char ch;
int a;
scanf("\n");
for(scanf("%c",&ch);ch!='\n';scanf("%c",&ch))
{
if(ch=='[')
{
scanf("%d",&a);
scanf("%c",&ch);
for(int i=0;i<a;i++) str[size++]=ch;
scanf("%c",&ch);
}
else str[size++]=ch;
}
str[size]='\0';
for(int i=0;i<size;i++)
{
su[i]=str[size-1-i];
}
su[size]='\0';
}
int searchDFA(char *ss)
{
int ans=0;
node *p=tree+1,*tmp;
for(int i=0;ss[i];i++)
{
int idx=ss[i]-'A';
while(p->child[idx]==NULL&&p!=tree+1)
p=p->pre;
if(p->child[idx]) p=p->child[idx];
for(tmp=p;tmp!=NULL&&tmp->count!=-1;tmp=tmp->pre)
{
ans+=tmp->count;
tmp->count=-1;
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ncount=2;size=0;
memset(tree,0,sizeof(tree));
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
Insert(tree+1);
}
Input();
BuildDFA();
printf("%d\n",searchDFA(str)+searchDFA(su));
}
return 0;
}