#include<stdio.h>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int n,m,alen,blen,a[5100],b[5600];
struct ACatuomata{
int next[55600][256],fail[55600],idx[55600],last[55600],num,root;
bool vis[55600];
int newnode()
{
memset(next[num],0,sizeof next[num]);
idx[num]=0;
return num++;
}
void init()
{
num=0;
root=newnode();
}
void insert(int *s,int len,int id)
{
int cur=root;
for(int i=0;i<len;++i)
{
int &tmp=next[cur][s[i]];
if(!tmp)tmp=newnode();
cur=tmp;
}
idx[cur]=id;
}
void getfail()
{
queue<int>q;
fail[root]=root;
for(int i=0;i<256;++i)
{
int u=next[root][i];
if(u)
{
last[u]=fail[u]=0;
q.push(u);
}
}
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=0;i<256;++i)
{
int u=next[cur][i];
if(u)
{
fail[u]=next[fail[cur]][i];
last[u]=idx[fail[u]]?fail[u]:last[fail[u]];
q.push(u);
}
else next[cur][i]=next[fail[cur]][i];
}
}
}
int query(int *s,int len)
{
memset(vis,0,sizeof vis);
int cur=root,ret=0;
for(int i=0;i<len;++i)
{
cur=next[cur][s[i]];
int tmp=cur;
while(tmp!=root)
{
vis[idx[tmp]]=1;
tmp=last[tmp];
}
}
for(int i=1;i<=n;++i)
ret+=vis[i];
return ret;
}
}ac;
int DecodeIndex[]=
{
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x3E,0x40,0x40,0x40,0x3F,
0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x40,0x40,0x40,0x40,0x40,0x40,
0x40,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x40,0x40,0x40,0x40,0x40,
0x40,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x40,0x40,0x40,0x40,0x40
};
void Base64Decode(int* src,int* dest,int srclen)
{
for(int i=0;i!=srclen/4;i++)
{
*dest=((DecodeIndex[*src]<<2)|((DecodeIndex[*(src+1)]&0x30)>>4))%256;
*(dest+1)=((DecodeIndex[*(src+1)]<<4)|((DecodeIndex[*(src+2)]&0x3C)>>2))%256;
*(dest+2)=(((DecodeIndex[*(src+2)]&0x03)<<6)|(DecodeIndex[*(src+3)]&0x3F))%256;
src+=4;
dest+=3;
}
}
int main()
{
while(~scanf("%d",&n))
{
ac.init();
getchar();
for(int i=1;i<=n;++i)
{
char c;
while(c=getchar())
{
if(c=='\n')break;
a[alen++]=c;
if(c=='=')++blen;
}
Base64Decode(a,b,alen);
blen=alen/4*3-blen;
ac.insert(b,blen,i);
alen=blen=0;
}
ac.getfail();
scanf("%d",&m);
getchar();
while(m--)
{
char c;
while(c=getchar())
{
if(c=='\n')break;
a[alen++]=c;
if(c=='=')++blen;
}
Base64Decode(a,b,alen);
blen=alen/4*3-blen;
printf("%d\n",ac.query(b,blen));
alen=blen=0;
}
puts("");
}
}
题意:给出n个匹配串,有m个询问,对于每个询问,会给出一个原串,求原串中出现过几种匹配串。
这个题的匹配串和原串都是加了密的需要自己解密。
比较坑的就是他问的是种类而不是次数。
比如匹配串ab,原串abab,也只会返回1。
所以这个就不能保存cnt然后扫描的时候cnt++
这个题同样不能break。
就多加一个vis数组,也同样保存匹配串的下标,然后把vis[下标]设为1,最后统计有多少vis为1的就是答案,记得每次询问要清空vis。
错了很多次,不过都是没搞懂题意的时候为了弄懂题意而错的。。