隐藏口令
问题描述
有时候程序员有很奇怪的方法来隐藏他们的口令。
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为口令。
注:如果按照规则有两个字符串都是最小的,则取前面那一个。
总结
1. 初始化双指针 i=0、j=1,k=0(偏移量)
2. 比较 s [(i+k)% n] 和 s [(j+k)% n],根据大小关系移动指针
3. 最终取 i、j 中较小值,即为最小表示的起始索引(0 开始),直接输出该索引
#include <iostream>
#include <string>
using namespace std;
int findMinIndex(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 += k + 1;
} else {
j += k + 1;
}
if (i == j) {
j++;
}
k = 0;
}
}
return min(i, j);
}
int main() {
int L;
string s, temp;
cin >> L;
while (cin >> temp) {
s += temp;
if (s.size() >= L) {
break;
}
}
s = s.substr(0, L);
int result = findMinIndex(s);
cout << result << endl;
return 0;
}
求字符串的起始位置
问题描述
在程序设计中,对字符串的处理是经常遇到的一个问题。
例如,将字符串中所有的英文字母变成大写,或者将一个字符串与另一个字符串连接构成一个新的字符串。
由于此类的操作非常普遍,因此,在设计程序语言的时候,设计者就已经把这类操作的代码写好了,如果编程人员要使用这些代码,只需把该类代码的头文件包含到自己的程序中,编程人员就可以很简单的调用,这样使编程节省了不少时间。
明明是一名项目经理,他现在负责一种新的程序设计语言的开发,现在需要预先实现大量的和处理字符串有关的功能方法,以后这些方法会包含到程序设计语言中,方便程序语言使用者的开发。你是明明手下的一名软件工程师,明明分配给你一个任务,在两个字符串中,找到一个字符串在另一个字符串中的起始位置。 例如,有两个字符串,一个字符串s= “abc”,另一个字符串subs=“bc”,现在就要找出“bc”在“abc”中的其实位置,在这个例子中,“bc”的起始位置为2。
明明的问题可以归结为:输入两串字符串s和subs,求s中subs的起始位置。
总结
1. 循环读取多组 s 和 subs,直到输入结束;
2. 遍历原字符串 s 的每个可能起始位置,截取与 subs 长度相同的子串进行比较
3. 找到则返回 “索引 + 1”(转换为 1 开始的位置),未找到则返回 0
#include <iostream>
#include <string>
using namespace std;
int findSubstringPos(const string &s, const string &subs) {
int s_len = s.size();
int sub_len = subs.size();
if (sub_len == 0 || sub_len > s_len) {
return 0;
}
for (int i = 0; i <= s_len - sub_len; ++i) {
bool match = true;
for (int j = 0; j < sub_len; ++j) {
if (s[i + j] != subs[j]) {
match = false;
break;
}
}
if (match) {
return i + 1;
}
}
return 0;
}
int main() {
string s, subs;
while (getline(cin, s)) {
if (!getline(cin, subs)) {
break;
}
int pos = findSubstringPos(s, subs);
cout << pos << endl;
}
return 0;
}
最长的单词
问题描述
明明刚开始学习英语的时候,对英语有浓厚的兴趣,但是随着时间的推移,英语单词量的增加,明明越来越觉得背单词是一件相当痛苦的事情。于是他想出各种各样的方法来增加背单词的乐趣。
这次他想出的方法是把所有要背的英语单词排成一行,找出其中最长的一个单词来先背,然后划去这个单词,在剩下的单词中再找出一个最长的单词来背,以此类推,直到把所有单词都背完。如果有多个长度相同的单词,则先背一行中靠前的那个单词。这样做的好处是:背到越后面,单词越短,越容易背,越能增加背单词的信心。
例如有这么一行单词: one two three four five 明明会首先挑出three来背,因为它是最长的一个单词,由5个字母组成;然后明明会选择four这个单词,虽然five这个单词的长度和four这个单词的长度一样,但是four在five的前面,所以明明会先背four这个单词,然后再背five,等明明把five这个单词背完以后,接着背one这个单词,最后背的是two这个单词。
但是在这样背单词之中,明明又发现了另一个问题,当要背非常多的单词时,寻找最长的单词会花很多时间,他想让你帮助他写一个程序,找出一行单词中最长的那个,节约明明背单词所花的时间,与此同时,明明希望你能告诉他这个英文单词有多少个字母组成,那他可以做到心里有数。
明明的问题可以归结为:在一行英文单词中,找出其中最长的单词(若有多个最长,找出第一个出现的),并输出这个单词的长度。
总结
1.逐行读取输入,用字符串流分割每行的单词(自动处理多个空格);
2. 遍历分割后的单词,记录长度最长且最先出现的单词
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
string line;
while (getline(cin, line)) {
istringstream iss(line);
string word, max_word;
int max_len = 0;
while (iss >> word) {
int len = word.size();
if (len > max_len) {
max_len = len;
max_word = word;
}
}
if (!max_word.empty()) {
cout << max_len << " " << max_word << endl;
}
}
return 0;
}
计算机英语翻译
在 20 世纪 70 年代,计算机芯片制造商开始大规模生产微处理器 —— 这是一种作为计算机中主要信息处理中心的电子电路。
这项新技术彻底改变了计算机行业,它大幅降低了制造计算机的成本,并极大地提高了计算机的处理速度。微处理器的出现,让个人电脑的诞生成为可能,这也导致计算机应用的使用出现了爆发式增长。在 20 世纪 70 年代初到 80 年代之间,计算机科学领域迅速发展,致力于为个人电脑开发新的应用,并推动计算行业的技术进步。许多早期完成的研究成果开始通过个人电脑走向大众,而这些个人电脑的早期软件,大多源自已有的概念和系统。
单词打卡


269

被折叠的 条评论
为什么被折叠?



