HNU 11704 Baidu Post Bar

http://acm.hnu.cn/online/?action=problem&type=show&id=11704&courseid=0

题意:给你一堆语法规则,再给你一个表达式,问你这个表达式是否合法。

思路:DFA,构造一个有限状态自动机,然后进行状态转移。

代码:

#include<stdio.h>
#include<string.h>
#include<ctype.h>

const int MAXN = 10010 ;
int N, M ;
struct Node{
	int f ;
	struct Node *next[26] ;
}p1[500010] ,*root1 ,p2[500010] ,*root2 ;
int cnt1,cnt2; 
char pp[211000] ;

char name[20] ;
void Build1(char *ch){
	int i, j ,idx; 
	i = 0 ;
	Node *loc = root1 ,*q ;
	for( ; ch[i] != 0; i++){
		idx = ch[i] - 'a' ;
		if(loc->next[idx] == NULL){
			q = &p1[cnt1] ;	q->f = 0; 
			memset(q->next , 0 ,sizeof(q->next));
			loc->next[idx] = q ;
			cnt1 ++ ;
		} 
		loc = loc->next[idx] ;
	}
	loc->f = 1 ;
}
void Build2(char *ch){
	int i, j ,idx; 
	i = 0 ;
	Node *loc = root2 ,*q ;
	for( ; ch[i] ; i++){
		idx = ch[i] - 'a' ;
		if(loc->next[idx] == NULL){
			q = &p2[cnt2] ;
			q->f = 0; 
			memset(q->next , 0 ,sizeof(q->next));
			loc->next[idx] = q ;
			cnt2 ++ ;
		}
		loc = loc->next[idx] ;
	}
	loc->f = 1 ;
}

int f[10][10] ;

	void Init(){
	memset(f , -1 ,sizeof(f));
	f[1][1] = 2 ;
	f[2][2] = f[8][2] = 3 ;
	f[3][4] = 8 ;
	f[3][3] = 4 ;
	f[4][2] = f[6][2] = 5 ;
	f[5][4] = 6 ;
	f[5][6] = 7 ;
	f[5][5] = 2 ;
}
bool is_noun(char *ch){
	Node *loc = root1 ;
	int idx ;
	for(int i=0;ch[i]!=0;i++){
		idx = ch[i] - 'a' ;
		if( loc->next[idx] == NULL)	return false ;
		loc = loc->next[idx] ;
	}
	return loc->f ; 
}
bool is_verb(char *ch){
	Node *loc = root2 ;
	int idx ;
	for(int i=0;ch[i]!=0;i++){
		idx = ch[i] - 'a' ;
		if( loc->next[idx] == NULL)	return false ;
		loc = loc->next[idx] ;
	}
	return loc->f ;
}
bool is_and(char *ch){
	return strcmp(ch , "and") == 0;
}
bool is_one(char *ch){
	return strcmp(ch , ",") == 0 ;
}
int judge(char *ch){
	int i , j ;
	if( is_noun(ch) )	return 0 ;
	if( is_verb(ch) )	return 1 ;
	if( is_and(ch) )	return 2 ;
	if( is_one(ch) )	return 3 ;
	return -1 ;
}
/*
prefix : 1 
noun : 2 
verb : 3
and : 4
, : 5 
sufix : 6 

*/
bool DFA(){
	int state = 1 ;
	int len = strlen(pp);
	int i= 0 ,j;
	while(i<len && (pp[i]==' '||pp[i]=='\t') ) i++ ;
	if( pp[i]!='[')	return false ;
	bool blank = 0 ;
	for( ;i<len && pp[i]!=']';i++){
		if(pp[i]==' ' || pp[i]=='\t'){
			blank = 1 ; break ;
		}
	}
	if(blank)	return false ;
	i++ ;
	j = len - 1 ;
	while(j>=i && (pp[j]==' '||pp[j]=='\t'))	j-- ;
	if(pp[j] != ']')	return false ;
	blank = 0 ;
	for( ;j>=i && pp[j]!='[';j--){
		if(pp[j]==' ' || pp[j]=='\t'){
			blank = 1 ; break ;
		}
	}
	if(blank)	return false ;
	j-- ; 
	while(j>=i && (pp[j]==' '||pp[j]=='\t'))	j-- ;
	len = j + 1;
	state = f[state][1] ;
	while(i<len){
		while(i<len && (pp[i]==' '||pp[i]=='\t'))	i++ ;
		for(j=0 ;i<len ;i++ , j++){
			if( pp[i]!=' ' && pp[i]!='\t' ){
				name[j] = pp[i] ;
			}	
			else	break ;
		}
		name[j] = 0 ;
		int kind = judge(name);
		switch(kind){
			case 0 :	state = f[state][2] ; break ;
			case 1 :	state = f[state][3] ; break ;
			case 2 :	state = f[state][4] ; break ;
			case 3 :	state = f[state][5] ; break ;
			default :	return false ;
		}
		if(state == -1)	return false ;
	}
	return true ;
}
int main(){
	while(scanf("%d %d",&N,&M) == 2){
		root1 = &p1[0] ;
		root1->f = 0 ;  cnt1 = 1 ;
		memset(root1->next, 0 ,sizeof(root1->next));
		for(int i=0;i<N;i++){
			scanf("%s",name);
			Build1(name); 
		}		
		root2 = p2 ;
		root2->f = 0 ;  cnt2 = 1 ;
		memset(root2->next, 0 ,sizeof(root2->next));
		for(int i=0;i<M;i++){
			scanf("%s",name);
			Build2(name); 
		}
		getchar() ;
		gets(pp);
		Init(); 
		if(DFA())	printf("a good title\n");
		else 		printf("a bad title\n");
	}
	return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值