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 ;
}