题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4114
题目的意思:
给你一个加密的字符串,让你用二进制表示,每六位一个字符
然后再用8位二进制表示一个明文的字符,这是翻译的过程。
给你一些病毒的暗文,再给你一些长的字符串的暗文
问你每个长字符串暗文中出现了几种病毒,看清楚,是几种,不是几个。我为此WA了一个下午
此题分两步,一是要翻译
而是裸的AC自动机
裸的AC是很简单的
但是翻译的坑很大。
暗文都是可见字符,但是翻译过来的是ASCII在0~255之间的
所以不能用char来保存翻译后的,得用int
相应的长度也要做变化。
完成翻译之后就是裸的AC自动机了。
在进行统计的时候要注意,如果这个字符串之前统计了,就不要统计了
因为是问的种数,我WA了一个下午啊,说多了都是眼泪啊。
下面上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxlb=80000;
int erjin[maxlb];
char p[10000];
char text[10000];
int changetmp[10000];
int cha(char c)
{
if(c>='A'&&c<='Z')
return c-'A';
if(c>='a'&&c<='z')
return c-'a'+26;
if(c>='0'&&c<='9')
return c-'0'+52;
if(c=='+')
return 62;
return 63;
}
//先写转换函数
void change(char *s)
{
int len=strlen(s);
while(s[len-1]=='=')//忽略后面加入的=
len--;
s[len]='\0';
memset(erjin,0,sizeof(erjin));
for(int i=0;i<len;i++)
{
int tmp=cha(s[i]);
for(int j=6*(i+1)-1;j>=6*i;j--)//把转换后的先换成二进制,每个字符六位
{
if(tmp&1)
erjin[j]=1;
tmp=tmp>>1;
}
}
int len2 = len*6 / 8;
for(int i=0;i<len2;i++)
{
int tmp=0;
for(int j=8*i;j<=8*(i+1)-1;j++)
tmp=(tmp<<1)+erjin[j];
changetmp[i]=tmp;
}
changetmp[len2]=-1;
}
int findlen(int *s)
{
int len = 0;
while(s[len]>=0)
len++;
return len;
}
const int maxnode = 50000;
const int size_char=300;
int ans;
struct AC
{
int ch[maxnode][size_char];
int f[maxnode];
int last[maxnode];
int val[maxnode];
bool vis[maxnode];
int sz;
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
memset(vis,false,sizeof(vis));
}
void tongji(int x)
{
if(x&&!vis[x])
{
ans++;
vis[x]++;
tongji(last[x]);
}
}
void insert(int *s,int v)
{
int n=findlen(s);
int u=0;
for(int i=0;i<n;i++)
{
int c=s[i];
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
void find(int *T)
{
int n=findlen(T);
int u=0;
for(int i=0;i<n;i++)
{
int c=T[i];
while(u&&!ch[u][c])//沿着失配边走
u=f[u];
u=ch[u][c];
if(val[u])
tongji(u);
else if(last[u])
tongji(last[u]);
}
}
//构造f和last
void getfail()
{
queue<int>q;
int u=0;
f[0]=0;
for(int i=0;i<size_char;i++)
{
u=ch[0][i];
if(u)
{
f[u]=0;
q.push(u);
last[u]=0;
}
}
while(!q.empty())
{
int r=q.front();
q.pop();
for(int i=0;i<size_char;i++)
{
u=ch[r][i];
if(!u)
continue;
q.push(u);
int v=f[r];
while(v&&!ch[v][i])
v=f[v];
f[u]=ch[v][i];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}
};
AC ac;
int main()
{
int n;
while(~scanf("%d",&n))
{
ac.init();
for(int i=1;i<=n;i++)
{
scanf("%s",p);
change(p);
ac.insert(changetmp,i);
}
ac.getfail();
int m;
scanf("%d",&m);
while(m--)
{
ans=0;
memset(ac.vis,false,sizeof(ac.vis));
scanf("%s",text);
change(text);
ac.find(changetmp);
printf("%d\n",ans);
}
printf("\n");
}
return 0;
}