码迷,mamicode.com
首页 > 其他好文 > 详细

ZOJ - 3430 ac自动机

时间:2017-09-29 09:59:00      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:while   str   sed   double   put   lap   printf   debug   build   

这题主要就是解码过程很恶心,不能用char存,一共wa了20发

题意:先给n串加密后的字符,然后m串加密后的字符,解码之后求n对应每个m的匹配数,很显然的ac自动机

加密过程是先用对应ascii表的标号来代替字符,然后把这些数字转换成8位的二进制,全部连起来,然后每6位算一个数,用二进制算成整数,最后用这些整数来映射给定的表

题解:反解密就好了,要注意细节,很容易Segmentation Fault,最后算出来的字符用int存,然后跑ac自动机就行了

技术分享
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=520*64+10,maxn=60000+10,inf=0x3f3f3f;

inline void debug(){cout<<"fuck"<<endl;}

char s[4000];
int de[4000],sz;
int digit[4000*6];
struct Trie{
    int tot,root;
    int Next[N][256],fail[N],End[N];
    int newnode()
    {
        for(int i=0;i<256;i++)
            Next[tot][i]=-1;
        End[tot]=0;
        return tot++;
    }
    void init()
    {
        tot=0;
        root=newnode();
    }
    void insertstring(int id)
    {
        int now=root;
        for(int i=0;i<sz;i++)
        {
            if(Next[now][de[i]]==-1)
                Next[now][de[i]]=newnode();
            now=Next[now][de[i]];
        }
        End[now]=id;
    }
    void build()
    {
        queue<int>q;
        fail[root]=root;
        for(int i=0;i<256;i++)
        {
            if(Next[root][i]==-1)Next[root][i]=root;
            else
            {
                fail[Next[root][i]]=root;
                q.push(Next[root][i]);
            }
        }
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            for(int i=0;i<256;i++)
            {
                if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i];
                else
                {
                    fail[Next[now][i]]=Next[fail[now]][i];
                    q.push(Next[now][i]);
                }
            }
        }
    }
    bool vis[550];
    int query(int n)
    {
        int now=root;
        memset(vis,0,sizeof vis);
        for(int i=0;i<sz;i++)
        {
            now=Next[now][de[i]];
            int te=now;
            while(te!=root)
            {
                if(End[te])vis[End[te]]=1;
                te=fail[te];
            }
        }
        int res=0;
        for(int i=1;i<=n;i++)
            if(vis[i])
                res++;
        return res;
    }
};
int getnew(char x)
{
    if(x>=A&&x<=Z)return x-A;
    if(x>=a&&x<=z)return x-a+26;
    if(x>=0&&x<=9)return x-0+52;
    if(x==+)return 62;
    else return 63;
}
void change(char s[])
{
    sz=0;
    int len=strlen(s);
    while(s[len-1]===)len--;
    vector<int>v;
    for(int i=0;i<len;i++)v.pb(getnew(s[i]));
    memset(digit,0,sizeof digit);
    for(int i=0;i<v.size();i++)
    {
        for(int j=6*(i+1)-1;j>=6*i;j--)
        {
            if(v[i]&1)digit[j]=1;
            v[i]/=2;
        }
    }
    sz=v.size()*6/8;
    for(int i=0;i<sz;i++)
    {
        de[i]=0;
        for(int j=8*i;j<8*(i+1);j++)
            de[i]=(de[i]<<1)+digit[j];
       // cout<<de[i]<<" ";
    }
   // cout<<endl;
}
Trie ac;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    while(~scanf("%d",&n))
    {
        ac.init();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
            change(s);
            ac.insertstring(i);
        }
        ac.build();
        int k;
        scanf("%d",&k);
        while(k--)
        {
            scanf("%s",s);
            change(s);
            printf("%d\n",ac.query(n));
        }
        puts("");
    }
    return 0;
}
/********************

********************/
View Code

 

ZOJ - 3430 ac自动机

标签:while   str   sed   double   put   lap   printf   debug   build   

原文地址:http://www.cnblogs.com/acjiumeng/p/7609463.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!