poj 3746——Teacher YYF

题意:判断一些句子是否符合语法规则。
思路:题目给出了一些单词的词性。词性共有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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值