ZOJ - 3430 ac自动机
Posted walfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ - 3430 ac自动机相关的知识,希望对你有一定的参考价值。
这题主要就是解码过程很恶心,不能用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; } /******************** ********************/
以上是关于ZOJ - 3430 ac自动机的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ3228 Searching the String(AC自动机)
ZOJ3228 Searching the String (AC自动机)