UVALive 6523 Languages

时间:2023-03-09 03:18:07
UVALive 6523 Languages

传送门

The Enterprise has encountered a planet that at one point had been inhabited. The only remnant from the prior civilization is a set of texts that was found. Using a small set of keywords found in various different languages, the Enterprise team is trying to determine what type of beings inhabited the planet.

Input

The first line of input will be N (1 ≤ N ≤ 100), the number of different known languages. The next N lines contain, in order, the name of the language, followed by one or more words in that language, separated with spaces. Following that will be a blank line. After that will be a series of lines, each in one language, for which you are to determine the appropriate language. Words consist of uninterrupted strings of upper or lowercase ASCII letters, apostrophes, or hyphens, as do the names of languages. No words will appear in more than one language. No line will be longer than 256 characters. There will be at most 1000 lines of sample text. Every sample text will contain at least one keyword from one of the languages. No sample text will contain keywords from multiple languages. The sample text may contain additional punctuation (commas, periods, exclamation points, semicolons, question marks, and parentheses) and spaces, all of which serve as delimiters separating keywords. Sample text may contain words that are not keywords for any specific language. Keywords should be matched in a case-insensitive manner.

Output

For each line of sample text that follows the blank line separating the defined languages, print a single line that identifies the language with which the sample text is associated.

Sample Input

4

Vulcan throks kilko-srashiv k’etwel

Romulan Tehca uckwazta Uhn Neemasta

Menk e’satta prah ra’sata

Russian sluchilos

Dif-tor heh, Spohkh. I’tah trai k’etwel

Uhn kan’aganna! Tehca zuhn ruga’noktan!

Sample Output

Vulcan

Romulan

Solution

注意Input加粗的部分,我在这里WA了一发。

这题的输入是个坑。首先考虑如何读取Keywords,这可归结为读入一行内的若干字符串

在本题中,一行输入可分为两部分:words(词), delimiters(定界符、分隔符)。

delimiters又分为两种:whitespace characters(空白字符), punctuations(标点)。

keywords部分的输入,delimiters不含puntuations。如果没有读入一行这个设定的话,

char s[];

scanf("%s", s);

就搞定了。加了这个限制,只要把每个word后面的delimiters也读入,看其中是否包含'\n'就好了:

char s[], delim[];

scanf("%s%[ \n]", s, delim);

这里有个地方要特别注意:

在Windows下换行符是'\n\r' (line feed + carriage return),此时按上面代码中的方式读取delimiters就不能读取/r,但Windows下的换行符并不总是'\n\r',也有只是'\n'的情况,可能跟文件的扩展名有关吧,这个问题我暂不清楚。我调试时是从无扩展名的文本文件in读入的,换行符是'\n',不知换成in.txt会如何。但无论如何

char s[], delim[];

scanf("%s%[ \n\r]", s, delim);

都能正确处理。

-------------------------------------------------------------------------------------------------------------

sample text的输入要多考虑punctuations,可如此处理:

char s[], delim[];

scanf("%*[,.!;() \n]"), scanf("%[^,.!;() \n]%[,.!;() \n]", s, delim);

这样写其实有点多余,下面Implementation里的第二份代码给出了另一种做法。

注意这里如果写成

char s[], delim[];

scanf("%*[,.!;() \n]%[^,.!;() \n]%[,.!;() \n]", s, delim);

就错了。(请考虑函数scanf()在什么情况下return)

Implementation

#include <bits/stdc++.h>
using namespace std;
const int N();
map<string, int> mp;
char lang[N][], s[], delim[];
string t; int main(){
int n;
scanf("%d", &n);
for(int i=; i<n; i++){
scanf("%s", lang[i]);
for(bool flag=false; !flag;){
scanf("%s%[ \n]", s, delim);
for(int i=; s[i]; i++)
s[i]=tolower(s[i]);
t=s;
mp[t]=i;
for(int i=; delim[i]; i++)
if(delim[i]=='\n'){
flag=true;
break;
}
}
} for(bool flag=false; scanf("%*[,.!;() \n]"), ~scanf("%[^,.!;() \n]%[,.!;() \n]", s, delim); ){
if(!flag){
for(int i=; s[i]; i++)
s[i]=tolower(s[i]);
t=s;
if(mp.find(t)!=mp.end()){
flag=true;
puts(lang[mp[t]]);
}
}
for(int i=; delim[i]; i++)
if(delim[i]=='\n'){
flag=false;
break;
}
}
}
#include <bits/stdc++.h>
using namespace std;
const int N();
map<string, int> mp;
char lang[N][], s[], delim[];
string t; int main(){
int n;
scanf("%d", &n);
for(int i=; i<n; i++){
scanf("%s", lang[i]);
for(bool flag=false; !flag;){
scanf("%s%[ \n]", s, delim);
for(int i=; s[i]; i++)
s[i]=tolower(s[i]);
t=s;
mp[t]=i;
for(int i=; delim[i]; i++)
if(delim[i]=='\n'){
flag=true;
break;
}
}
}
scanf("%*[,.!;() \n]");
for(bool flag=false; ~scanf("%[^,.!;() \n]%[,.!;() \n]", s, delim); ){
if(!flag){
for(int i=; s[i]; i++)
s[i]=tolower(s[i]);
t=s;
if(mp.find(t)!=mp.end()){
flag=true;
puts(lang[mp[t]]);
}
}
for(int i=; delim[i]; i++)
if(delim[i]=='\n'){
flag=false;
break;
}
}
}