poj3746——map妙用+枚举

题目链接:poj.org/problem?id=3746

As we all know, grammar is very important when learning English. Now, YYF become a teacher of a primary school. The students are good at memory so they can tell the meaning and the function (noun, verb …) of the words in the textbook. But, they cannot use these words properly.

In YYF’s mind, writing sentences is a good way to learn grammar. So he tells the student to write 20 sentences a day, using the word learned in the class. As YYF has a lot of student, he will receive many sentences from his student. What a horrible work to check all the sentences. You are one of YYF’s friends, so he asks you for help. You task is to write a program to check the sentences.

To make the work simple, YYF chooses a part of the grammar: All the words can be grouped into seven divisions (noun, pronoun, adjective, adverb, preposition, article, and verb). A verb can be transitive or intransitive. So we use "n.", "pron.", "adj.", "adv.", "prep.", "art.", "vt." and "vi." to be short of noun, pronoun, adjective, adverb, preposition, article, transitive verb and intransitive verb. If a word is marked as "v.", it can be used as either transitive verb or intransitive verb.

Here comes the sentence structure:
1. Subject + Intransitive Verb
2. Subject + Transitive Verb + Object

Noun and pronoun can be used as Subject or Object. When using a noun, an article should be placed ahead of it. A noun can be modified by an adjective and a verb can be modified by an adverb. When an adjective is used to modify a noun, it should be put between article and noun. When an adverb is used to modify a verb, it should be put ahead of the verb. A prepositional phrase can be put ahead of Subject, between Subject and Verb, behind Intransitive Verb, between Verb and Object, or behind Object. A prepositional phrase is made up of a preposition and a noun/pronoun. In one sentence, at most one prepositional phrase is allowed. Any two parts of the sentence cannot intersect. For example, "He is a good student" is OK, but "He a good is student" is not. Every word in the dictionary will have only one function. The words are not case sensitive and Subject-Verb Agreement does not matter. That’s all the rules. Now, it's your time to show.

Input

The input contains only one case.
The first line specifies two number N and M (1 ≤ N, M ≤ 5000). The next N lines will be the words and the functions. Every line contains a word and its function, separated by a space. The next M lines will be the sentences -- one sentence per line. Each sentences contains at most 20 words. Every word in the sentences will appear in the dictionary.

Output

The output contains M lines. For each line, output "YES" if the sentence is OK, and output "NO" if not.

Sample Input

10 6
he pron.
see vt.
a art.
baby n.
at prep.
the art.
airport n.
happy adj.
guess v.
immediately adv.
He guess.
He see baby.
Happy he see a baby.
He immediately see a baby.
He see a baby immediately.
At the airport, he see a happy baby.

Sample Output

YES
NO
NO
YES
NO
YES

Hint

Please read the Problem Description carefully. Do not use your own English knowledge to construct rules.

题目翻译:

众所周知,语法在学习英语时非常重要。现在,YYF成为一所小学的老师。学生们善于记忆,所以能说出课本中单词的意思和功能(名词、动词等)。但是,他们不能正确使用这些词。‎

‎在YYF的心目中,写句子是学习语法的好方法。因此,他告诉学生每天写20个句子,使用在课堂上学到的单词。由于YYF有很多学生,他将会从他的学生那里获得许多句子。检查所有的句子是件多么可怕的工作啊。你是YYF的朋友之一,所以他请求你帮忙。你的任务是写一个程序来检查句子。‎

‎为了使工作简单,YYF选择了语法的一部分:所有的单词可以分为七个部分(名词、代词、形容词、副词、介词、文章和动词)。动词可以是传递的,也可以是过渡性的。因此,我们使用"n","pron","adj","adv","准备","艺术","vt"和"vi"来缺少名词、词名、形容词、副词、介词、文章、转序动词和不通性动词。如果一个单词被标记为"v.",它可以用作传递动词或不通性动词。‎

‎下面是句子结构:‎
‎1. 主题 + 不通‎
‎传递动词 2。主题 = 传递动词 + 对象‎

‎名词和词名可用作主题或对象。使用名词时,应将文章放在它前面。名词可以通过形容词修改,动词可以用副词修饰。当一个形容词被用来修饰一个名词时,它应该放在文章和名词之间。当使用副词修改动词时,应将其置于动词前面。介词短语可以放在"主体"之前、主体和动词之间、不通式动词后面、动词和对象之间或对象后面。介词短语由介词和名词/词名组成。在一个句子中,最多允许一个介词短语。句子的任何两个部分不能相交。例如,"他是个好学生"是可以的,但"他好就是学生"不是。字典中的每个单词都只有一个函数。单词不区分大小写,主题-Verb 协议并不重要。这就是所有的规则。现在,是时候展示了。‎

‎输入‎

‎输入仅包含一个大小写。‎
‎第一行指定两个数字‎‎N‎‎和‎‎M‎‎ (1 = ‎‎N‎‎, ‎‎M‎‎ = 5000)。下一个‎‎N‎‎行将是单词和函数。每行包含一个单词及其函数,由空格分隔。下一行‎‎是‎‎句子——每行一个句子。每个句子最多包含20个单词。句子中的每个单词都会出现在字典里。‎

‎输出‎

‎输出包含‎‎M‎‎行。对于每行,如果句子正常,则输出"YES",如果句子为"否",则输出"否"。

 

灰常恶心的一个题,情况挺多的,看的网上的代码给的589种情况,

这里抛出一个简单的版本

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <map>
#include <sstream>
using namespace std;

map<string,string> mp;
map<string,bool> ste;
map<string,char> str,fun;

void init(){
    fun["n."]='0';
    fun["pron."]='1';
    fun["adj."]='2';
    fun["adv."]='3';
    fun["prep."]='4';
    fun["art."]='5';
    fun["vt."]='6';
    fun["vi."]='7';
    fun["v."]='8';

    str["450"]='A'; //介词短语
    str["4520"]='A';
    str["41"]='A';
    str["1"]='S'; //主/宾语
    str["50"]='S';
    str["520"]='S';
    str["7"]='I'; //不及物谓语
    str["37"]='I';
    str["6"]='T'; //及物谓语
    str["36"]='T';
    str["8"]='V'; //通用谓语
    str["38"]='V';
    //句子可能的总体结构
    ste["SI"]=1;
    ste["STS"]=1;
    ste["SV"]=1;
    ste["SVS"]=1;
    ste["ASI"]=1;
    ste["ASTS"]=1;
    ste["ASV"]=1;
    ste["ASVS"]=1;
    ste["SAI"]=1;
    ste["SATS"]=1;
    ste["SAV"]=1;
    ste["SAVS"]=1;
    ste["SIA"]=1;
    ste["STAS"]=1;
    ste["SVA"]=1;
    ste["SVAS"]=1;
    ste["STSA"]=1;
    ste["SVSA"]=1;
}

bool check(string s){
    string res = "",c = "";
    for(int i = 0; i < s.size(); i++){
        c += s[i];
        if(str[c] > 0){
            res += str[c];
            c = "";
        }
    }
    res += c;
    if(ste[res])
        return true;
    return  false;
}

string work(string s){
    stringstream ss(s);
    string st,ans;
    while(ss>>st){
        int len = st.size(),flag = 0;
        st[0] = tolower(st[0]);
        if(st[len-1] == '.'){
            flag = 1;
            st.erase(--st.end());
        }
        if(st[len-1] == ',')
            st.erase(--st.end());
        ans += fun[mp[st]];
        if(flag && !check(ans))
            return "NO";
    }
    return "YES";
}

int main(){
    ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n,m;
    init();
    while(cin>>n>>m){
        mp.clear();
        string s,s1,s2;
        for(int i = 0; i < n; i++){
            cin>>s1>>s2;
            //cout << s1 << " " << s2 <<endl;
            mp[s1] = s2;
        }
        cin.get();
        for(int i = 0; i < m; i++){
            getline(cin,s);
            cout << work(s) << endl;
        }
    }
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值