day32:隐藏口令、求字符串的起始位置、最长的单词

隐藏口令

问题描述

有时候程序员有很奇怪的方法来隐藏他们的口令。

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 年代之间,计算机科学领域迅速发展,致力于为个人电脑开发新的应用,并推动计算行业的技术进步。许多早期完成的研究成果开始通过个人电脑走向大众,而这些个人电脑的早期软件,大多源自已有的概念和系统。

单词打卡

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值