例题 5-8 Unix Is 命令(Unix ls,UVA400)

我的思路是在输入时计算最大单词长度maxlen,计算列a:(60-maxlen)/(maxlen+2) + 1与行b:(n-1)/a + 1。然后对名字排序后按列输出,但我用行输出加上了一点计算。
cpp
#include <bits/stdc++.h>
using namespace std;
//一行60个字符
int main(){
int n;
freopen("in.txt","r",stdin);
while(cin >> n){
string name[n];
int maxlen = 0;
for(int i = 0;i<n;i++){
cin >> name[i];
int len = name[i].length();
if(len > maxlen) maxlen = len;
}
sort(name,name+n);
int a,b;//列数和行数
a = (60-maxlen)/(maxlen+2) + 1;
b = (n-1)/a + 1;
// cout << a << "列 " << b << "行" << endl;
for(int i = 0;i<60;i++) {cout << '-';}
cout << endl;
for(int i = 0;i<b;i++){
for(int j = 0;j<a;j++){
cout << name[b*j+i];
if(j != a-1){
int kong = maxlen-name[b*j+i].length() + 2;
while(kong--) cout << ' ';
}
}
cout << endl;
}
}
}
例题 5-9 数据库(数据库 Database UVA1592)
给出一个n行m列的数据库,是否存在两个不同行r1,r2和两个不同列c1,c2,使得这两行和这两列相同(即(r1,c1)和(r2,c1)相同,(r1,c2)和(r2,c2)相同)。
样例输入
3 3
How to compete in ACM ICPC,Peter,peter@neerc.ifmo.ru
How to win ACM ICPC,Michael,michael@neerc.ifmo.ru
Notes from ACM ICPC champion,Michael,michael@neerc.ifmo.ru
样例输出
YES
2 3
2 3
我的思路:
1.存入:读取每行字符串,每遇到一次逗号,就把逗号前面的数据拿出来作为now,在line(键值对)中查找键为now的值,没有找到,就存进去(索引为当前line容器的元素数量)。将返回的值存入table[i][col](行,列)中。记得要处理最后一列(没有逗号)。
2.查找:双循环代表列对的组合,对于每个列对的每行遍历,计算列对的值(将两列的值合并为一个),在循环过程中若找到两行列对值相同,退出循环,输出"YES"并输出行列值。
cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin >> n >> m;
cin.ignore(); // 重要!忽略第一行后面的换行符
map<string,int>data_line;
vector<vector<int>> table(n, vector<int>(m));
//按行存储每列的数据并将其转化为数字存到table[i][col]中
for(int i = 0;i<n;i++){
string line;
getline(cin,line);
string now = "";
int col = 0;//列数
for(char c : line){
if(c == ','){
if(!data_line.count(now)){//".count()"检查data_line中是否有为now的值(key)
data_line[now] = data_line.size();
}//将当前容器data_line的元素个数赋值给键<now>对应的值data_line[now]
table[i][col++] = data_line[now];//第i行第col列的值为 data_line[now]返回的值
now.clear();//清空当前处理的字符串(数据)
}else now += c;
}
// 处理最后一列
if (!data_line.count(now)) {
data_line[now] = data_line.size();
}
table[i][col] = data_line[now];
line.clear();//清空此行字符串
}
//开始按行查找
bool found = false;
int r1 = 0, r2 = 0, c1 = 0, c2 = 0;
// 枚举所有可能的列对
for (int i = 0; i < m && !found; i++) {//只要找到就退出
for (int j = i + 1; j < m && !found; j++) {
// 使用哈希表来记录每个 "值对" 第一次出现的行号
unordered_map<long long, int> seen;
for (int k = 0; k < n; k++) {
// 将两个整数组合成一个唯一的键
long long key = (long long)table[k][i] * 1000000LL + table[k][j];//乘上一个很大的数,避免重复
if (seen.count(key)) {
//找到了重复的值对
found = true;
r1 = seen[key] + 1; // 转换为1-based索引
r2 = k + 1;
c1 = i + 1;
c2 = j + 1;
break;
} else {
seen[key] = k; // 记录这个值对第一次出现的行号
}
}
}
}
// 输出结果
if (found) {
cout << "YES" << endl;
cout << r1 << " " << r2 << endl;
cout << c1 << " " << c2 << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
习题 5-10 在Web中搜索 (Searching the Web,UVa597)
输入n篇文章和m个请求(n<100,m≤50000),每个请求都是4种格式之一。
- A: 找包含关键字A的文章。
- A AND B: 找同时包含关键字A和B的文章。
- A OR B: 找包含关键字A或B的文章。
- NOT A: 找不包含关键字A的文章。
处理询问时需要对每篇文章输出证据。前3种询问输出所有至少包含一个关键字的行。第4种询问输出不包含A的整篇文章。关键字只由小写字母组成,查找时忽略大小写。每行不超过80字符,一共不超过1500行。

这道题比较好写,但是有许多题目没有给出的地方需要注意。建议看一下原题,由于槽点有很多,我就用dalao写的一份很详细的 题解 了。