与琪热恋 发表于 2021-5-7 20:44:55

子串

大贤者福尔的字符串研究取得了积极的进展,但他现在遇到了一个新的问题,他需要找到一个字符串的所有满足特殊条件的子串。他的问题具体来说是,对一个给定的字符串,按给定的子串大小N进行分割(N不超过字符串的长度),分割点位于依次位于字符串中相邻字符之间,使得最大子串的长度不超过N。同时,把分割后的所有子串依次拼接,就可以恢复为原始字符串。如给定字符串ABCDE,若N为1,则分割的子串为A B C D E;若N为2,根据起始分割点不同,可以有两种分割结果,分别为A BC DE和AB CD E。
福尔希望你能够帮他,找出他需要的所有子串。
输入
输入数据有若干行,第一行为一个长度不超过N(1≤N≤100)的字符串,字符串由大写英文字母组成。 随后的行中,每行为一个正整数x(1≤x≤N),数量不超过N个。
输出
对每组输入数据,先在单独的行中输出测试样例的编号Case x:,x为样例编号,从1开始。随后的行中,按顺序依次输出所有分割得到的子串。一种分割方式的结果输出到同一行中,存在多种不同的分割方式时,按起始分割点的从小到大的顺序在不同的行中输出分割结果。
示例输入
ABCDE
1
2
3
示例输出
Case 1:
A B C D E
Case 2:
A BC DE
AB CD E
Case 3:
A BCD E
AB CDE
ABC DE
各位大佬看看吧

yuxijian2020 发表于 2021-5-7 22:20:13

本帖最后由 yuxijian2020 于 2021-5-8 09:41 编辑

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

constexpr size_t MAX_LEN = 50;

struct Part
{
    size_t start;
    size_t len;

    Part() : start(0), len(0) {}
    Part(size_t s, size_t l) : start(s), len(l) {}
};

class StringSplitPlan
{
public:
    StringSplitPlan()                   = delete;

    explicit StringSplitPlan(StringSplitPlan& other) :
                  str(other.str), len(other.len), splits(other.splits) {}
   
    explicit StringSplitPlan(StringSplitPlan&& other)
    {
      str = move(other.str);
      len = other.len;
      splits.swap(other.splits);
    }

    explicit StringSplitPlan(const string& str) : str(str), len(1) { this->Split(); }
    explicit StringSplitPlan(const string &str, size_t len) : str(str), len(len) { this->Split(); }

    const string& GetString() const { return str; }
    size_t GetLen() const { return len; }
    const vector<vector<Part>>& GetArray() const { return splits; }

    void PrintAll() const
    {
      printf_s("Case %lld:\n", len);

      for(const auto& vec : splits)
      {
            for(const auto& part : vec)
                printf_s("%s ", string(str, part.start, part.len).c_str());

            printf_s("\n");
      }
    }

private:
    void Split()
    {
      for (size_t pos = 1; pos <= len; ++pos)
      {
            vector<Part> temp;
            size_t start = 0, end = pos;
            temp.emplace_back(Part(start, end - start));

            do
            {
                start = end;
                end += len;
                temp.emplace_back(Part(start, end - start));

            } while (end <= str.size());

            splits.emplace_back(temp);
      }
    }

    //待分割字符串
    string str;
    //每块长度
    size_t len;
    //分割后的下标数组
    vector<vector<Part>> splits;
};

char* GetInputString()
{
    char* temp = new char;
    memset(temp, 0, MAX_LEN);
    char c   = 0;
    int    i   = 0;

    while((c = getchar()) != '\n')
      temp = c;

    if(temp == '\r')
      temp = '\0';

    return temp;
}

int main()
{
    string str;
    size_t len;
    vector<StringSplitPlan> result;
    char* c;

    printf_s("请输入一个字符串:");
    cin >> str;
    getchar();

    while(1)
    {
      printf_s("请输入分割后的子串的最大长度(直接回车则结束输入):");
      c = GetInputString();

      if(strlen(c) == 0)
            break;

      len = static_cast<size_t>(atoll(c));
      delete[] c;

      if(len > str.size())
      {
            printf_s("子串长度不能大于原字符串!\n");
            continue;
      }

      result.emplace_back(StringSplitPlan(str, len));
    }

    for(const auto& i : result)
      i.PrintAll();

    return 0;
}


页: [1]
查看完整版本: 子串