题意:判断一些句子是否符合语法规则。
思路:题目给出了一些单词的词性。词性共有9种。首先分别给词性编号。
n. 0
pron. 1
adj. 2
adv. 3
prep. 4
art. 5
vt. 6
vi. 7
v. 8
一个句子只有两种形式,主语加不及物动词,主语加及物动词加宾语。
主语(sub)和宾语共有三种形式,(5,2,0)(5,0)(1)
谓语可以有六种形式([3],6)([3],7)([3],8),方括号代表可有可无
介词短语(prepositional phrase)有两种形式(4,5,0)(4,1)。介词短语可以在一个句子中任意一个地方。
题目的数据貌似有些问题。题目中说句子中每个成分不能有交叉。但是貌似介词短语可以在别的成分中间。比如He immediately see a at he baby. 介词在宾语中间,但是却是对的。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<assert.h>
using namespace std;
int n,m;
const char func[10][10]={ "n.", "pron.", "adj.", "adv.", "prep.", "art.", "vt." , "vi.","v."};
void C(char *a)
{
int len=strlen(a);
for(int i=0;i<len;++i){
if(a[i]>='A'&&a[i]<='Z')a[i]=a[i]-'A'+'a';
}
}
struct Word
{
char w[105];
int f;
Word(char *a="",char *b="")
{
strcpy(w,a);
int i;
for(i=0;i<9;++i){
if(strcmp(b,func[i])==0)break;
}
f=i;
}
bool operator < (const Word &a) const {
return strcmp(w,a.w)<0;
}
}word[5005];
int find(char *s)
{
int l=0;
int r=n;
while(l<r){
int m=(l+r)>>1;
int tmp=strcmp(word[m].w,s);
if(tmp==0){
// cout<<s<<' '<<word[m].w<<' '<<word[m].f<<endl;
return word[m].f;
}
if(tmp<0){
l=m+1;
} else {
r=m-1;
}
}
// cout<<s<<' '<<word[l].w<<' '<<word[l].f<<endl;
return word[l].f;
}
struct Sentence
{
int tot;
char w[25][105];
int rec[25];
bool sub;
int v;
int obj;
int pp;
int pt;
Sentence()
{
pp=-1;
pt=0;
tot=0;
sub=0;
v=0;
obj=0;
char s[100];
cin.getline(s,100,'\n');
// cout<<s<<endl;
int len=strlen(s);
for(int i=0;i<len;++i){
if(s[i]>='A'&&s[i]<='Z'){
s[i]=s[i]-'A'+'a';
} else if(s[i]>='a'&&s[i]<='z')continue;
else {
s[i]=' ';
}
}
// cout<<s<<endl;
s[len]=' ';
s[len+1]='\0';
len=strlen(s);
for(int i=0;i<len;){
if(s[i]!=' '){
w[tot][0]='\0';
int wlen=0;
int j=i;
for(;j<len;j++){
if(s[j]==' ')break;
w[tot][wlen++]=s[j];
}
w[tot][wlen++]='\0';
// cout<<w[tot]<<' ';
tot++;
i=j;
}
i++;
}
// cout<<endl;
}
bool check()
{
memset(rec,-1,sizeof(rec));
for(int i=0;i<tot;++i){
rec[i]=find(w[i]);
// cout<<w[i]<<' '<<rec[i]<<endl;
}
for(int i=0;i<tot;++i){
if(rec[i]==4){
if(rec[i+1]==5&&rec[i+2]==0){//450
if(pp>=0)return false;
for(int j=i+3;j<tot;++j){
rec[j-3]=rec[j];
}
tot-=3;
pp=i;pt=3;
} else if((rec[i+1]==1)){//41
if(pp>=0)return false;
for(int j=i+2;j<tot;++j){
rec[j-2]=rec[j];
}
tot-=2;
pp=i;pt=2;
} else return false;
}
}
int p=0;
while(p<tot){
// if(p==pp){cout<<1/0;p+=pt;continue;}
if(rec[p]==4)cout<<1/0;
if(sub==0){
if(rec[p]==5&&rec[p+1]==2&&rec[p+2]==0){
sub=1;
p=p+3;
} else if(rec[p]==5&&rec[p+1]==0){
p=p+2;
sub=1;
} else if(rec[p]==1){
p=p+1;
sub=1;
} else return false;
} else if(v==0){
if(rec[p]==3)p++;
if(rec[p]==6){
v=6;
p++;
} else if(rec[p]==7){
v=7;
p++;
} else if(rec[p]==8){
v=8;
p++;
} else return false;
} else if(obj==0){
if(v==7)return false;
if(rec[p]==5&&rec[p+1]==2&&rec[p+2]==0){
obj=1;
p=p+3;
} else if(rec[p]==5&&rec[p+1]==0){
p=p+2;
obj=1;
} else if(rec[p]==1){
p=p+1;
obj=1;
} else return false;
} else return false;
}
if(v==6&&obj==0)return false;
if(!sub)return false;
if(!v)return false;
return true;
}
};
int main()
{
// freopen("data.txt","r",stdin);
scanf("%d%d",&n,&m);
char a[105];
char b[20];
for(int i=0;i<n;++i){
scanf("%s%s",a,b);
C(a);
C(b);
word[i]=Word(a,b);
}
sort(word,word+n);
getchar();
while(m--){
Sentence s;
printf(s.check()?"YES":"NO");
puts("");
}
return 0;
}