HDU 3695 Computer Virus on Planet Pandora(AC自动机)

链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3695


题目大意:

给出n个匹配串,然后给一个长串S,找出S中有多少种匹配串。注意匹配串在S中正反出现的顺序都算是出现。

S可能会有些段是压缩过的,格式为【qx】,q是一个数字,x是一个字母,代表有q个x。 假设 把B【3A】DE“解压缩”之后,就是

BAAADE


分析与总结:

一开始没弄清题意,以为是求所有病毒的总数量,结果一直TLE。。其实这题要求的是源码中有多少种病毒。一旦找到一个病毒,就把Trie中的那个单词标记为false.

另外把“压缩”的网站源码进行“解压缩”的步骤也要细心点,容易出错。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int MAXN = 5200005;
const int MAX_NODE = 3000005;
const int SIGMA_SIZE = 26;

char str[MAXN];
char buf[MAXN];

struct node{
    node* fail;
    node* next[SIGMA_SIZE];
    bool isword;
    int  id;
    void init(){
        id=0;
        isword=false;
        memset(next, 0, sizeof(next));
    }
};

class AC_Automation{
public:
    void init();
    void insert(char*,int);
    void getFail();
    int  find(char*);

private:
    node* new_node();
    int ID(char ch){return ch-'A';}

private:
    node Heap[MAX_NODE];
    node* root;
    int size;
};

node* AC_Automation::new_node(){
    Heap[size].init();
    return &Heap[size++];
}
void AC_Automation::init(){
    size=0;
    root=new_node();
}

void AC_Automation::insert(char* str,int id){
    node* p=root;
    for( ; *str; ++str){
        int ch=ID(*str);
        if(p->next[ch] == NULL)
            p->next[ch] = new_node();
        p = p->next[ch];
    }
    p->isword=true;
    p->id=id;
}
void AC_Automation::getFail(){
    queue<node*>Q;
    Q.push(root);
    while(!Q.empty()){
        node* tmp=Q.front(); Q.pop();
        for(int i=0; i<SIGMA_SIZE; ++i){
            node*& now = tmp->next[i];
            if(now != NULL){
                Q.push(now);
                if(tmp==root) now->fail=root;
                else{
                    node* p=tmp->fail;
                    while(p != NULL){
                        if(p->next[i] != NULL){
                            now->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p==NULL) now->fail=root;
                }
            }
            else{
                if(tmp==root) now = root;
                else now=tmp->fail->next[i];
            }
        }
    }
}
int AC_Automation::find(char* str){
    node* p=root;
    int cnt=0;
    for( ; *str; ++str){
        int ch=ID(*str);
        p = p->next[ch];
        if(p==NULL) p=root;
        node* tmp=p;
        while(tmp!=root && tmp->isword){
            ++cnt;
            tmp->isword=false;
            tmp = tmp->fail;
        }
    }
    return cnt;
}

// 字符串转置 
inline void rev(char* str, int len){
    char ch;
    for(int i=0, k=len-1; i<len/2; ++i,--k){
        ch=str[i]; str[i]=str[k]; str[k]=ch;
    }
}
// 字符串“解压缩”
inline void change(char* str,char* now){
    memset(now, 0, sizeof(now));
    int len=strlen(str);
    int i;
    for(i=0; i<len; ++i){
        if(str[i]=='['){
            ++i;
            int num=0;
            while(str[i]>='0' && str[i]<='9'){
                num = num*10 + str[i] - '0';
                ++i;
            }
            while(num--){
                *now = str[i];
                ++now;
            }
            ++i; 
        }
       else{
            *now=str[i];
            ++now;
        }
    }
}

AC_Automation ac;

int main(){
    int n,nCase;
    char pat[1005];
    scanf("%d",&nCase);
    while(nCase--){
        ac.init();
        scanf("%d%*c",&n);
        for(int i=1; i<=n; ++i){
            gets(pat);
            ac.insert(pat, i);
        }
        ac.getFail();
        memset(buf, 0, sizeof(buf));
        memset(str, 0, sizeof(str));
        gets(buf);
        change(buf,str);
        int ans=ac.find(str);
        rev(str,strlen(str));
        printf("%d\n", ans+ac.find(str));
    }
    return 0;
}


 ——  生命的意义,在于赋予它意义士。

          原创 http://blog.csdn.net/shuangde800 , By   D_Double  (转载请标明)



你可能感兴趣的:(HDU 3695 Computer Virus on Planet Pandora(AC自动机))