ZJU 3430 Detect the Virus AC自动机

来源:互联网 发布:telnet 80端口失败 编辑:程序博客网 时间:2024/05/20 20:05

思路:把字符串解码后,就是一个果的AC自动机。

坑点:
  • 解码后的字符十进制大小0~255,不能用char,需要用unsigned char。
  • 解码的过程使用位操作会非常简单
  • chr = chr - 'a' + 26 不能写成chr -= 'a' + 26,这个地方WA了很多发。

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4114

/*********************************************    Problem : ZJU 3430    Author  : NMfloat    InkTime (c) NM . All Rights Reserved .********************************************/#include <map>#include <set>#include <queue>#include <stack>#include <cmath>#include <ctime>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#define rep(i,a,b)  for(int i = (a) ; i <= (b) ; i ++) //遍历#define rrep(i,a,b) for(int i = (b) ; i >= (a) ; i --) //反向遍历#define repS(it,p) for(auto it = p.begin() ; it != p.end() ; it ++) //遍历一个STL容器#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next) //遍历u所连接的点#define cls(a,x)   memset(a,x,sizeof(a))#define eps 1e-8using namespace std;const int MOD = 1e9+7;const int INF = 0x3f3f3f3f;typedef long long LL;typedef unsigned long long ULL;typedef unsigned char UC;int T,n,m,k;int fx[] = {0,1,-1,0,0};int fy[] = {0,0,0,-1,1};const int MAXN = 5e4;const int MAX_SIZE = 256;int tot ; char s[10005];UC buf[10005];bool vis[525];class AC_automation {private:       struct Node {        int next[MAX_SIZE]; //节点的儿子        int stat ; //有几个字符是以当前节点结尾的    }t[MAXN]; //Trie 树上的节点    int fail[MAXN]; //失配指针public:        void init() {        tot = 1; cls(t,0); cls(fail,0);    }    static void tr(char & chr) {        if(chr >= 'A' && chr <= 'Z') chr = chr - 'A';        else if(chr >= 'a' && chr <= 'z') chr = chr - 'a' + 26; //注意不能写成chr -= 'a' + 26;        else if(chr >= '0' && chr <= '9') chr = chr - '0' + 52;         else if(chr == '+') chr = 62;        else chr = 63;    }    void insert(UC * str,int len,int id) {        int now = 0;        rep(i,0,len) {            if(!t[now].next[str[i]]) {                t[now].next[str[i]] = tot ++;            }            now = t[now].next[str[i]];        }        t[now].stat = id;    }    void get_fail() {        queue<int>q;        q.push(0);        while(!q.empty()) {            int u = q.front();            rep(i,0,MAX_SIZE-1) {                if(t[u].next[i]) {                    q.push(t[u].next[i]);                    int tmp = u;                    while(fail[tmp]) {                        if(t[fail[tmp]].next[i]) {                            fail[t[u].next[i]] = t[fail[tmp]].next[i]; break;                        }                        tmp = fail[tmp];                    }                     if(u != 0 && !fail[t[u].next[i]]) {//处理fail[tmp] = 0 时的情况                        if(t[0].next[i]) fail[t[u].next[i]] = t[0].next[i];                    }                }            }            q.pop();        }        //rep(i,1,tot-1) printf("%d %d %d\n",i,fail[i],t[i].stat);      }    int query(UC * str,int len) {        int now = 0;        cls(vis,0);        rep(i,0,len) {            while(now && (!t[now].next[str[i]])) now = fail[now];            now = t[now].next[str[i]];            int tmp = now;            while(tmp) {                vis[t[tmp].stat] = true;                             tmp = fail[tmp];            }        }        int ret = 0;        rep(i,1,n) {            if(vis[i]) ret ++;        }        return ret;    }};void decode(char * str , int & len) {    int slen = strlen(str) - 1;    while(str[slen]=='=') slen --;    rep(i,0,slen) AC_automation::tr( str[i] ) ;    rep(i,0,slen) buf[i] = str[i];    for(int i = 0 ; i <= slen ; i += 4) {        buf[++len] = ( (buf[i]<<2) | (buf[i+1]>>4) );        if(i + 2 <= slen) buf[++len] = ( (buf[i+1]<<4) | (buf[i+2]>>2));        if(i + 3 <= slen) buf[++len] = ( (buf[i+2]<<6) | (buf[i+3]));    } }AC_automation ac;void input() {    ac.init();    char str[1005];    rep(i,1,n) {        scanf("%s",str);        int len = -1;        decode(str,len);        ac.insert(buf,len,i);    }    ac.get_fail();}void solve() {    scanf("%d",&m);    rep(i,1,m) {        scanf("%s",s);        int len = -1;        decode(s,len);        printf("%d\n",ac.query(buf,len));    }    puts("");}int main(void) {    //freopen("a.in","r",stdin);    while(~scanf("%d",&n)) {        input();        solve();    }    return 0;}
0 0
原创粉丝点击