ZOJ 3430 Detect the Virus(AC自动机)

 

给出 n 个模式串以 base64 编码,再给出 m 个文本串以 base64 编码,问这 m 个文本串中出现过多少次模式串 

题目若是没有以 base64 编码为条件就是一道 AC自动机的模板题,但是区区一个编码就变成了自闭题

首先搞清楚 base64 编码的规则,题目中已经给出了 hello 的样例,就是将 hello 的 acsll 码转化为二进制,然后每 6 位按题目中给出的表进行对字符进行转化,= 忽略即可

而题目要求我们求文本串的匹配,自然要将给出的 base64 进行解码,由于 base64 每个字符只有 6 位,而文本串有 8 位,所以将 4 位 base64 字符转化为 3 位文本串即可

然而题目真正需要注意的是

  1. char 的范围 [-128,127] 所以文本串需要用 unsigned char 来存储
  2. 题目中给出的文本串的长度最长为 2048,但是输入时的以 base64 编码的模式串将超过 2048
  3. 在解码的过程中可能出现 0,所以不能以 0 作为文本串结束的标志
const int N=512*64+5;

    int n,m;
    int i,j,k;
    int t[N][256],tot=0;
    int f[N],vis[N];
    char s[2048+5<<1];
    unsigned char ch[2048+5];
    set<int> all;

int idx(char ch)
{
    int ans=0;
    if(ch>='A' && ch<='Z') return ch-'A';
    ans+=26;
    if(ch>='a' && ch<='z') return ch-'a'+26;
    ans+=26;
    if(ch>='0' && ch<='9') return ch-'0'+52;
    if(ch=='+') return 62;
    return 63;
}

int update(char *s)
{
    int len=strlen(s);
    if(s[len-1]=='=') len--,s[len]=0;
    if(s[len-1]=='=') len--,s[len]=0;
    for(int i=0;i<len;i++) s[i]=idx(s[i]); //00111111
    int ans=0;
    for(int i=0;i<len;i+=4){
        ch[ans++]=((s[i]<<2)|(s[i+1]>>4));
        if(i+2<len) ch[ans++]=((s[i+1]<<4)|(s[i+2]>>2));
        if(i+3<len) ch[ans++]=((s[i+2]<<6)|s[i+3]);
    }
    return ans;
}

void insert(unsigned char *s,int id,int len)
{
    int rt=0;
    for(int i=0;i<len;i++){
        int x=s[i];
        if(!t[rt][x]) t[rt][x]=++tot;
        rt=t[rt][x];
    }
    vis[rt]=id;
}

void getfail()
{
    int rt=0;
    queue<int> q;
    for(int i=0;i<256;i++) if(t[rt][i]) q.push(t[rt][i]),f[t[rt][i]]=0;
    while(q.size()){
        rt=q.front(); q.pop();
        for(int i=0;i<256;i++){
            if(t[rt][i]) f[t[rt][i]]=t[f[rt]][i],q.push(t[rt][i]);
            else t[rt][i]=t[f[rt]][i];
        }
    }
}

void query(unsigned char *s,int len)
{
    all.clear();
    int rt=0;
    for(int i=0;i<len;i++){
        int x=s[i];
        rt=t[rt][x];
        for(int j=rt;j;j=f[j]) if(vis[j]) all.insert(vis[j]);
    }
}

void clear()
{
    for(int i=0;i<=tot;i++){
        vis[i]=f[i]=0;
        for(int j=0;j<256;j++) t[i][j]=0;
    }
    tot=0;
}

int main()
{
    //IOS;
    while(~sd(n)){
        for(int i=1;i<=n;i++){
            ss(s);
            int len=update(s);
            insert(ch,i,len);
        }
        getfail();
        sd(m);
        for(int i=1;i<=m;i++){
            ss(s);
            int len=update(s);
            query(ch,len);
            //for(set<int>::iterator it=all.begin();it!=all.end();it++) pd(*it);
            pd(all.size());
        }
        clear();
        puts("");
    }
    //PAUSE;
    return 0;
}

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页