内容:oj基础92 93 94+U12sectionBP13 14 15+单词100
oj基础92
明明最近在做一个有关字符串的统计工作。两个由小写字母组成的字符串s1和s2,明明需要统计出以下四种关系:
(1)在s1或s2中存在的字母(包括在s1和s2中都存在的字母);
(2)在s1中且在s2中的字母;
(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母;
(4)不在s1中且也不在s2中的字母;
例如两个字符串s1为"lkjsvoahs",s2为"qglhskjdfg":
(1)在s1或者在s2或者s1、s2中都存在的字母:adfghjkloqsv;
(2)在s1中且在s2中的字母:hjkls;
(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母:adfgoqv;
(4)不在s1中且也不在s2中的字母:bceimnprtuwxyz;
明明统计了很久,但是由于统计过程十分繁琐,且很容易出错,导致明明的进度非常慢,很有可能因为统计不完而错过了晚上的约会。因此明明想请你帮个忙,帮他写一个程序,用程序来统计出以上几项内容。
明明的问题可以归结为:
输入两串由小写字母组成的字符串s1和s2,比较其中的字母,输出以下四项,输出的字母以字典顺序排列:
(1)在s1或s2中存在的字母(包括在s1和s2中都存在的字母);
(2)在s1中且在s2中的字母;
(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母;
(4)不在s1中且也不在s2中的字母;
例如字符串s1为sadf,s2为asdf,则需输出以下四行(注意输出的格式):
in s1 or s2:adfs
in s1 and s2:adfs
in s1 but not in s2 ,or in s2 but not in s1:
not in s1 and s2:bceghijklmnopqrtuvwxyz
cpp
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string s1, s2;
bool firstCase = true;
while (getline(cin, s1) && getline(cin, s2)) {
if (!firstCase) {
cout << endl;
}
firstCase = false;
// 标记 s1 和 s2 中出现的字母
bool inS1[26] = {false};
bool inS2[26] = {false};
for (char c : s1) {
if (c >= 'a' && c <= 'z') {
inS1[c - 'a'] = true;
}
}
for (char c : s2) {
if (c >= 'a' && c <= 'z') {
inS2[c - 'a'] = true;
}
}
string orStr = ""; // (1) A并 B
string andStr = ""; // (2) A 交 B
string xorStr = ""; // (3) A 异或B
string neitherStr = ""; // (4) 全集 - (A ∪并 B)
for (int i = 0; i < 26; i++) {
char c = 'a' + i;
bool in1 = inS1[i];
bool in2 = inS2[i];
if (in1 || in2) {
orStr += c;
}
if (in1 && in2) {
andStr += c;
}
if ((in1 && !in2) || (!in1 && in2)) {
xorStr += c;
}
if (!in1 && !in2) {
neitherStr += c;
}
}
cout << "in s1 or s2:" << orStr << endl;
cout << "in s1 and s2:" << andStr << endl;
cout << "in s1 but not in s2 ,or in s2 but not in s1:" << xorStr << endl;
cout << "not in s1 and s2:" << neitherStr << endl;
}
return 0;
}
oj基础93
有时候程序员有很奇怪的方法来隐藏他们的口令。
Billy"Hacker"Geits会选择一个字符串S(由L个小写字母组成,5<=L<=100,000),然后他把S顺时针绕成一个圈。
如字符串cbadfa,绕成一个圈后,我们认为字符串首尾相连。
每次取其中一个字母作为起始字母,并顺时针依次取字母而组成一个字符串。这样将得到一些字符串。
比如字符串cbadfa,按照以上规则取出的字符串有:
cbadfa badfac adfacb dfacba facbad acbadf
我们找到最小的那个字符串,可知为acbadf,也可知道它的第一个字符'a'在原字符串cbadfa中为第6个字符(位置从1开始),
将得到的结果6减1得到5,这就是我们需要的口令。
再比如字符串alabala,绕成一个圈后,每次取其中一个字母作为起始字母,并顺时针依次取字母而组成一个字符串。这样将得到一些字符串:
alabala labalaa abalaal balaala alaalab laalaba aalabal
我们找到最小的那个字符串,可知为aalabal,它的第一个字母'a'在原字符串中位置为7,7-1=6,则6为口令。
注:如果按照规则有两个字符串都是最小的,则取前面那一个
cpp
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
// 返回最小旋转的起始下标
int minRepresentation(const string& s) {
int n = s.size();
int i = 0, j = 1, k = 0;
while (i < n && j < n && k < n) {
char a = s[(i + k) % n];
char b = s[(j + k) % n];
if (a == b) {
k++;
} else {
if (a > b) {
i = i + k + 1;
} else {
j = j + k + 1;
}
if (i == j) j++;
k = 0;
}
}
return min(i, j);
}
int main() {
int L;
cin >> L;
cin.ignore();
string s = "";
while ((int)s.length() < L) {
string line;
getline(cin, line);
for (char c : line) {
if (islower(c)) { // 只取小写字母
s += c;
}
}
}
// 确保 s 长度为 L
s = s.substr(0, L);
int pos = minRepresentation(s);
cout << pos << endl;
return 0;
}
新思想:双指针法
cpp
int minRepresentation(string s) {
int n = s.length();
int i = 0, j = 1, k = 0;
while (i < n && j < n && k < n) {
char a = s[(i + k) % n];
char b = s[(j + k) % n];
if (a == b) {
k++;
} else {
if (a > b) {
i = i + k + 1;
} else {
j = j + k + 1;
}
if (i == j) j++;
k = 0;
}
}
return min(i, j);
}
oj基础95
明明刚开始学习英语的时候,对英语有浓厚的兴趣,但是随着时间的推移,英语单词量的增加,明明越来越觉得背单词是一件相当痛苦的事情。于是他想出各种各样的方法来增加背单词的乐趣。
这次他想出的方法是把所有要背的英语单词排成一行,找出其中最长的一个单词来先背,然后划去这个单词,在剩下的单词中再找出一个最长的单词来背,以此类推,直到把所有单词都背完。如果有多个长度相同的单词,则先背一行中靠前的那个单词。这样做的好处是:背到越后面,单词越短,越容易背,越能增加背单词的信心。
例如有这么一行单词: one two three four five 明明会首先挑出three来背,因为它是最长的一个单词,由5个字母组成;然后明明会选择four这个单词,虽然five这个单词的长度和four这个单词的长度一样,但是four在five的前面,所以明明会先背four这个单词,然后再背five,等明明把five这个单词背完以后,接着背one这个单词,最后背的是two这个单词。
但是在这样背单词之中,明明又发现了另一个问题,当要背非常多的单词时,寻找最长的单词会花很多时间,他想让你帮助他写一个程序,找出一行单词中最长的那个,节约明明背单词所花的时间,与此同时,明明希望你能告诉他这个英文单词有多少个字母组成,那他可以做到心里有数。
明明的问题可以归结为:在一行英文单词中,找出其中最长的单词(若有多个最长,找出第一个出现的),并输出这个单词的长度。
cpp
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
string line;
while (getline(cin, line)) {
stringstream ss(line);
string word;
string longestWord = "";
size_t maxLen = 0;
while (ss >> word) {
if (word.length() > maxLen) {
maxLen = word.length();
longestWord = word;
}
}
cout << maxLen << " " << longestWord << endl;
}
return 0;
}
利用 stringstream 自动跳过任意数量空格
翻译
P13
许多人可能最初是通过电视广播接触到 AR 的,即作为对实况转播画面的标注。这种概念最早且最著名的例子是美式橄榄球中的虚拟"首攻线",它标示了获得首攻所需的码数,直接叠加在比赛的电视转播画面上。这种用虚拟覆盖层标注电视画面的概念已成功应用于许多其他体育项目,包括棒球、冰球、赛车和帆船。图 12B-3 展示了一场带有增强功能的电视转播足球比赛。这种形式的 AR 观众无法改变视角。鉴于赛场上的实况是通过跟踪摄像机捕捉的,交互式视角变换仍然是可能的,尽管不在终端观众的控制之下。
P14
几家相互竞争的公司为各种广播赛事提供增强解决方案,创造令人信服且具有信息量的实况标注。标注的可能性早已不仅仅局限于体育信息或简单的线条图形,现在还包括复杂的品牌标识或产品广告的 3D 图形渲染
P15
利用类似的技术,不仅可能,而且实际上在当今的电视广播中很常见------即在虚拟演播室环境中呈现主持人和其他电视名人的形象。在这一应用中,主持人是在绿幕前通过跟踪摄像机拍摄的,并被插入到演播室的虚拟渲染中。该系统甚至允许对虚拟道具进行交互式操作。
单词
