zoj 3430

这个题解码部分比较繁琐,剩下就是裸AC自动机了。

代码能力不强竟然调试了一天。。。。

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
const int kind=256;
using namespace std;
char b[3000];    //a模式串,b为匹配串
bool vis[550];
int bb[3000];
int mp[200];
int length;
struct trie{
	struct trie * fail,*next[kind];
	int count;
	int id;
	trie(){
		fail=NULL;
		count=0;
		memset(next,NULL,sizeof(next));
	}
};
struct trie * root;
void insert(int* str,int len,int id){
	int i,tem;
	struct trie *p,*q;
	p=root;
	for(i=0;i<len;i++){
		tem=str[i];
		if(p->next[tem]==NULL){
			q=(struct trie*)calloc(1,sizeof(struct trie));
			q->count=0;
			q->fail=NULL;
			memset(q->next,NULL,sizeof(q->next));
			p->next[tem]=q;
		}
		p=p->next[tem];
	}
	p->count+=1;
	p->id=id;
}
void buildac(){
	int i;
	struct trie *p,*tem;
	queue<struct trie *>q;
	root->fail=NULL;
	q.push(root);
	while(!q.empty()){
		tem=q.front();
		q.pop();
		for(i=0;i<kind;i++){
			if(tem->next[i]!=NULL){
				if(tem==root)
					tem->next[i]->fail=root;
				else{
					p=tem->fail;
					while(p!=NULL){
						if(p->next[i]!=NULL){
							tem->next[i]->fail=p->next[i];
							break;
						}
						p=p->fail;
					}
					if(p==NULL)
						tem->next[i]->fail=root;
				}
				q.push(tem->next[i]);
			}
		}
	}
}
int query(int *str,int len){
	int i,tem,result=0;
	struct trie* tmp=root,*p;
	for(i=0;i<len;i++){
		tem=str[i];
		while(tmp->next[tem]==NULL && tmp!=root)
			tmp=tmp->fail;
		tmp=tmp->next[tem];
		if(tmp==NULL)
			tmp=root;
		p=tmp;
		while(p!=root && vis[p->id]==0){            //每到一个位置就加上p->count,以及以他的后缀为前缀的单词
			if(p->id!=0)
				vis[p->id]=1;                       //这里我WA了一天
			result+=p->count;
			p=p->fail;
		}
	}
	return result;
}
void decode(){
	int i,j,len;
	len=strlen(b);
	if(b[len-1]=='=' && b[len-2]=='=')
		length=((len-2)*6-4)/8;
	else if(b[len-1]=='=' && b[len-2]!='=')
		length=((len-1)*6-2)/8;
	else if(b[len-1]!='=' && b[len-2]!='=')
		length=len*6/8;
	for(i=0,j=0;j<len-4;i+=3,j+=4){
		bb[i]=(mp[b[j]]<<2)+(mp[b[j+1]]>>4);
		bb[i+1]=((mp[b[j+1]]&15)<<4)+(mp[b[j+2]]>>2);
		bb[i+2]=((mp[b[j+2]]&3)<<6)+(mp[b[j+3]]);
	}
	bb[i]=(mp[b[j]]<<2)+(mp[b[j+1]]>>4);
	if(b[len-2]!='=')
		bb[i+1]=((mp[b[j+1]]&15)<<4)+(mp[b[j+2]]>>2);
	if(b[len-1]!='=')
		bb[i+2]=((mp[b[j+2]]&3)<<6)+(mp[b[j+3]]);
}
void init(){
	int i;
	for(i='A';i<='Z';i++)
		mp[i]=i-'A';
	for(i='a';i<='z';i++)
		mp[i]=i-'a'+26;
	for(i='0';i<='9';i++)
		mp[i]=i-'0'+52;
	mp['+']=62;
	mp['/']=63;
}
void destroy(struct trie * r){
	for(int i=0;i<kind;i++)
		if(r->next[i]!=NULL)
			destroy(r->next[i]);
	delete(r);
}
int main(){
	//freopen("a.txt","r",stdin);
	//freopen("c.txt","w",stdout);
	int t,T,n,m,i,j,sum;
	init();
	while(scanf("%d",&n)!=EOF){
		root=(struct trie*)calloc(1,sizeof(struct trie));
		root->fail=NULL;
		root->count=0;
		memset(root->next,NULL,sizeof(root->next));
		for(i=1;i<=n;i++){
			scanf("%s",b);
			memset(bb,0,sizeof(bb));
			decode();
			//printf("*****");
			//for(int k=0;k<length;k++)
			//	printf("%d ",bb[k]);
			//printf("\n");
			insert(bb,length,i);
		}
		buildac();
		scanf("%d",&m);
		for(i=1;i<=m;i++){
			scanf("%s",b);
			memset(bb,0,sizeof(bb));
			decode();
			//printf("*****");
			//for(int k=0;k<length;k++)
			//	printf("%d ",bb[k]);
			//printf("\n");
			memset(vis,0,sizeof(vis));
			printf("%d\n",query(bb,length));
		}
		printf("\n");
		destroy(root);         //这里释放内存空间降低内存使用
	}
	return 0;
}

写了个暴跑程序对拍才看出哪错了。。。
 

 

你可能感兴趣的:(zoj 3430)