这道题要留意的是转换后的字符,是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;
}