[hdu3695]Computer Virus on Planet Pandora(AC自动机)

题意:正反匹配模式串。

解题关键:需要建立vis数组,不然会超时,因为匹配串会匹配很多次模式串,而我们只记录一次,从而第二次以后可以直接break。

复杂度可从$O(500W)$降到$O(25W)$

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int N=26;
  5 const int MAXN=250010;
  6 bool vis[MAXN];
  7 int ans;
  8 struct Trie{//数组形式 
  9     int Next[MAXN][N],Fail[MAXN],End[MAXN],root,tot;//大小为所以匹配字符串的总和 
 10     int newnode(){//结构体内部用 
 11         for(int i=0;i<N;i++) Next[tot][i]=-1;
 12         End[tot++]=0;
 13         return tot-1;
 14     }
 15     void init(){
 16         tot=0;
 17         root=newnode();
 18     }
 19     void insert(char buf[]){
 20         int len=strlen(buf);
 21         int now=root;//now是temp指针 
 22         for(int i=0;i<len;i++){
 23             int k=buf[i]-'A';
 24             if(Next[now][k]==-1)  Next[now][k]=newnode();//next数组代表的是下一个字符索引 
 25             now=Next[now][k];
 26         }
 27         End[now]++;//end数组是当前字符串的个数.字典中可能有相同的单词,若只算一次,改为1. 
 28     }
 29     void build(){//构造fail指针,后缀是某些前缀 
 30         queue<int>que;
 31         Fail[root]=root;
 32         for(int i=0;i<N;i++){ 
 33             if(Next[root][i]==-1) Next[root][i]=root;
 34             else{
 35                 Fail[Next[root][i]]=root;
 36                 que.push(Next[root][i]);
 37             }
 38         } 
 39         while(!que.empty()){//bfs,会将所有的匹配子串都遍历到 
 40             int now=que.front();
 41             que.pop();
 42             for(int i=0;i<N;i++){
 43                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
 44                 else{
 45                     Fail[Next[now][i]]=Next[Fail[now]][i];//fail指向最长的 
 46                     que.push(Next[now][i]);
 47                 }
 48             }
 49         }
 50     }
 51     void query(char buf[]){
 52         int len=strlen(buf),now=root,res=0;
 53         for(int i=0;i<len;i++){
 54             now=Next[now][buf[i]-'A'];
 55             int temp=now;
 56             while(temp!=root){
 57                 if(vis[temp]) break;
 58                  ans+=End[temp];
 59                  End[temp]=0;
 60                  vis[temp]=true;
 61                 temp=Fail[temp];
 62             }
 63         }
 64     }
 65 };
 66 
 67 Trie ac;
 68 char buf[5100010];
 69 int n,m;
 70 int input(){
 71     getchar();
 72     char ch;
 73     int slen=0;
 74     while((ch=getchar())!='\n'){
 75         if(ch!='[') buf[slen++]=ch;
 76         else{
 77             int x;
 78             scanf("%d%c",&x,&ch);
 79             while(x--) buf[slen++]=ch;
 80             getchar();
 81         }
 82     }
 83     buf[slen]='\0';
 84     return slen;
 85 }
 86 
 87 
 88 int main(){
 89        int t;
 90        scanf("%d",&t);
 91        while(t--){
 92            memset(vis,0,sizeof vis);
 93            ans=0;
 94            ac.init();
 95            scanf("%d",&n);
 96            for(int i=0;i<n;i++){
 97                scanf("%s",buf);
 98                ac.insert(buf);
 99         }
100         ac.build();
101         int len=input();
102         ac.query(buf);
103         reverse(buf,buf+len);
104         ac.query(buf);
105         printf("%d\n",ans);
106     }
107     return 0;
108 } 

 

posted @ 2017-09-12 02:07  Elpsywk  阅读(284)  评论(0编辑  收藏  举报