真心觉得trie图数组形式的好优越,原来指针版本的太搓了(TLE) 下面是TLE的程序 #includecstdio#includestdlib.h#includecstring#includequeueusing namespace std;int n;char str[52000010],str1[50120010];char s[2600][1
真心觉得trie图数组形式的好优越,原来指针版本的太搓了(TLE)
下面是TLE的程序
#include<cstdio>
#include<stdlib.h>
#include<cstring>
#include<queue>
using namespace std;
int n;
char str[52000010],str1[50120010];
char s[2600][1200];
bool flag[2600],ok[2600];
struct trie{
struct trie * fail ,*next[26];
int ok;
trie(){
fail=NULL;
ok=0;
memset(next,NULL,sizeof(next));
}
};
struct trie * root;
void insert(char * str,int id){
int len=strlen(str),i,tem,sum=0;
struct trie *p,*q;
p=root;
for(i=0;i<len;i++){
tem=str[i]-'A';
if(p->ok)sum++;
if(p->next[tem]==NULL){
q=(struct trie *)calloc(1,sizeof(struct trie));
q->fail=NULL;
memset(q->next,NULL,sizeof(q->next));
p->next[tem]=q;
}
p=p->next[tem];
}
p->ok=id;
}
void buildac(){
int i;
struct trie *p,*tem;
queue<struct trie *>q;
root->fail=NULL;
q.push(root);
while(!q.empty()){
tem=q.front();
q.pop();
for(i=0;i<26;i++){
if(tem->next[i]!=NULL){
if(tem==root)
tem->next[i]->fail=root;
else{
p=tem->fail;
while(p!=NULL){
if(p->next[i]!=NULL){
tem->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL)
tem->next[i]->fail=root;
}
q.push(tem->next[i]);
}
}
}
}
void change(char * str,char * str1){
int i,j,k,len=strlen(str);
k=0;
for(i=0;i<len;i++){
if(str[i]=='['){
i++;
int sum=0;
for(;str[i]>='0' && str[i]<='9';i++)
sum=sum*10+str[i]-'0';
for(j=1;j<=sum;j++)
str1[k++]=str[i];
i++;
}
else
str1[k++]=str[i];
}
str1[k]='\0';
}
int query(char * str){
int len=strlen(str),i,result=0,tem;
struct trie * tmp=root,* p;
for(i=0;i<len;i++){
tem=str[i]-'A';
while(tmp->next[tem]==NULL && tmp!=root)
tmp=tmp->fail;
tmp=tmp->next[tem];
if(tmp==NULL)
tmp=root;
p=tmp;
while(p!=root){
flag[p->ok]=1;
p=p->fail;
}
}
return result;
}
void sea(char * str,int id){
int len=strlen(str),i,result=0,tem;
struct trie * tmp=root,* p;
for(i=0;i<len;i++){
tem=str[i]-'A';
while(tmp->next[tem]==NULL && tmp!=root)
tmp=tmp->fail;
tmp=tmp->next[tem];
if(tmp==NULL)
tmp=root;
p=tmp;
while(p!=root){
if(p->ok!=id)
ok[p->ok]=0;
p=p->fail;
}
}
}
int main(){
int t,T;
int i,j,len,k;
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d",&n);
root=(struct trie *)calloc(1,sizeof(struct trie));
root->fail=NULL;
root->ok=0;
memset(root->next,NULL,sizeof(root->next));
for(i=1;i<=n;i++){
scanf("%s",str);
change(str,str1);
strcpy(s[i],str1);
insert(str1,i);
}
buildac();
scanf("%s",str);
change(str,str1);
memset(flag,0,sizeof(flag));
query(str1);
for(i=1;i<=n;i++)ok[i]=flag[i];
for(i=1;i<=n;i++)
if(flag[i])
sea(s[i],i);
int sum=0;
for(i=1;i<=n;i++)
if(ok[i])sum++;
printf("%d\n",sum);
}
return 0;
}
AC程序
#include <cstdio>
#include <cstring>
#include <queue>
#define N 3000000
using namespace std;
char s[5101000],s1[5101000],str[2600][1200];
int next[N][26],fail[N],flag[N],pos;
int ans,ok[3000];
bool vis[N];
int newnode(){
memset(next[pos],0,sizeof(next[pos]));
fail[pos]=flag[pos]=0;
return pos++;
}
void insert(char * s,int id){
int p=0,i=0;
for(;s[i];i++){
int k=s[i]-'A';
p=next[p][k]?next[p][k]:next[p][k]=newnode();
}
flag[p]=id; //这里由于模式串太多,不能状态记忆,否则可以更快
}
void makefail(){
queue<int>q;
q.push(0);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
int v=next[u][i];
if(v==0)next[u][i]=next[fail[u]][i];
else q.push(v);
if(v && u) fail[v]=next[fail[u]][i];
}
}
}
void findstr(char * s){
int p=0,i;
for(i=0;s[i];i++){
int k=s[i]-'A';
p=next[p][k];
if(flag[p]){
ok[flag[p]]=1;
continue;
}
for(int j=p;j && !vis[j];j=fail[j]){
vis[j]=1;
ok[flag[j]]=1;
}
}
}
void sea(char * s,int id){
int p=0,i;
for(i=0;s[i];i++){
int k=s[i]-'A';
p=next[p][k];
for(int j=p;j && !vis[j];j=fail[j]){
if(flag[j] && flag[j]!=id){
ok[flag[j]]=0;
vis[j]=1;
}
}
}
}
void change(){
int i,j,k,len,tem;
len=strlen(s);
for(i=j=0;i<len;){
if(s[i]!='['){
s1[j++]=s[i++];
}
else{
i++;
tem=0;
while(s[i]>='0' && s[i]<='9'){
tem=tem*10+s[i]-'0';
i++;
}
for(k=1;k<=tem;k++) s1[j++]=s[i];
i+=2;
}
}
s1[j]='\0';
}
int main(){
int t,T,n,i,j;
scanf("%d",&T);
for(t=1;t<=T;t++){
memset(vis,0,sizeof(vis));
memset(ok,0,sizeof(ok));
scanf("%d",&n);
pos=0;newnode();
for(i=1;i<=n;i++){
scanf("%s",str[i]);
strcpy(s,str[i]);
change();
strcpy(str[i],s1);
insert(s1,i);
}
makefail();
scanf("%s",s);
change();
findstr(s1);
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++) if(ok[i]) sea(str[i],i);
ans=0;
for(i=1;i<=n;i++) ans+=ok[i];
printf("%d\n",ans);
}
return 0;
}