这道题要留意的是转换后的字符,是0~255的..包括一些转义字符..譬如'\0'的..so..用字符串存会很囧..所以用int数组存...
本题分为两步...第一步是翻译字符串...第二步是AC自动机...
我对位运算很不熟练...所以在翻译字符串用的是最原始最原始的方法...先将字符串读入..转化为二进制串..再翻译成所需的...还好...虽然效率不高..但也没耽误太多时间..
第二步就是AC自动机模板题了...有好几个月没写AC自动机...发现自己写出来的和以前完全不同了...但感觉现在写的这个更为有效率,代码量也更小..本来就没必要递归来递归去的...
题目给了一段转化数据的代码段(是从输出的形式转化为输入的形式..)..虽然不能应用到程序里...但可以充分利用这个代码段来生成数据,检验自己的程序~~
我发现的问题就是...当前到达字典数的某个点..不仅要看这个点是否是病毒标记点..而且其fail不断上去有哪些是病毒标记点都要查询...我就因为这个WA了好久....后来想起利用题目中的代码段生成数据...立马找到错误了...
顺便提供一组数据吧:
Data:
7
YQ==
Yg==
YWI=
YWJj
YWJjZA==
YmNk
Y2Q=
1
YWJjZA==
Ans:
7
Program:
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; struct node { int virus,son[256],fail; }point[50000]; int n,m,ans,h,turn[256],l,temp[80000]; char ss[10000]; int s[10000]; queue<int> myqueue; bool used[600]; void change() { int i,len,k,j,p; len=strlen(ss); l=0; for (i=0;i<len;i++) if (ss[i]=='=') break; else { k=turn[ss[i]]; p=32; for (j=1;j<=6;j++) { temp[++l]=k/p; k=k%p; p/=2; } } for (;i<len;i++) l-=2; for (i=1;i<=l-7;i+=8) { k=0; for (j=0;j<=7;j++) k=k*2+temp[i+j]; s[i/8]=k; } l/=8; } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int i,k; for (i=0;i<=256;i++) { if (i>='A' && i<='Z') turn[i]=i-'A'; else if (i>='a' && i<='z') turn[i]=i-'a'+26; else if (i>='0' && i<='9') turn[i]=i-'0'+52; else if (i=='+') turn[i]=62; else turn[i]=63; } while (~scanf("%d",&n)) { m=0; point[0].virus=point[0].fail=0; memset(point[0].son,0,sizeof(point[0].son)); while (n--) { scanf("%s",ss); change(); k=0; for (i=0;i<l;i++) if (!point[k].son[s[i]]) { m++; point[k].son[s[i]]=m; point[m].virus=point[m].fail=0; memset(point[m].son,0,sizeof(point[m].son)); k=m; }else k=point[k].son[s[i]]; point[k].virus=n+1; } while (!myqueue.empty()) myqueue.pop(); for (i=0;i<256;i++) if (point[0].son[i]) myqueue.push(point[0].son[i]); while (!myqueue.empty()) { h=myqueue.front(); myqueue.pop(); for (i=0;i<256;i++) if (point[h].son[i]) { myqueue.push(point[h].son[i]); k=point[h].fail; while (k && !point[k].son[i]) k=point[k].fail; if (point[k].son[i]) point[point[h].son[i]].fail=point[k].son[i]; } } scanf("%d",&n); while (n--) { scanf("%s",ss); change(); memset(used,false,sizeof(used)); used[0]=true; ans=0; k=0; for (i=0;i<l;i++) { while (k && !point[k].son[s[i]]) k=point[k].fail; if (point[k].son[s[i]]) k=point[k].son[s[i]]; h=k; while (h) { if (!used[point[h].virus]) { ans++; used[point[h].virus]=true; } h=point[h].fail; } } printf("%d\n",ans); } printf("\n"); } return 0; }