1. 程式人生 > >ZOJ - 3430 ac自動機

ZOJ - 3430 ac自動機

ont ati long sca clas 全部 puts eve code

這題主要就是解碼過程很惡心,不能用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自動機