Lynn_oyl 发表于 2023-10-15 10:26:39

C++题目求助3

字符串最大跨距
说明
有三个字符串S,S1,S2,其中,S长度不超过300,S1和S2的长度不超过10。想检测S1和S2是否同时在S中出现,且S1位于S2的左边,并在S中互不交叉(即,S1的右边界点在S2的左边界点的左侧)。计算满足上述条件的最大跨距(即,最大间隔距离:最右边的S2的起始点与最左边的S1的终止点之间的字符数目)。如果没有满足条件的S1,S2存在,则输出-1。
例如,S = "abcd123ab888efghij45ef67kl", S1="ab", S2="ef",其中,S1在S中出现了2次,S2也在S中出现了2次,最大跨距为:18。
输入格式
三个串:S, S1, S2,其间以逗号间隔(注意,S, S1, S2中均不含逗号和空格);
输出格式
S1和S2在S最大跨距;若在S中没有满足条件的S1和S2,则输出-1。
样例
输入数据 1
abcd123ab888efghij45ef67kl,ab,ef
输出数据 1
18

我的代码:
#include <bits/stdc++.h>
using namespace std;
int a,b,cnt1,cnt2,mx=0;
int main(){
    string s,s1,s2;
    cin>>s>>s1>>s2;
    bool flag=0;
    for(int i=0;i<(int)s.size();i++){
      if(s.substr(i,s1.size())==s1){
            i+=s1.size()-1;
            a=i+s1.size()-1;
            cnt1++;
      }
      if(s.substr(i,s2.size())==s2){
            i+=s2.size()-1;
            b=i+s2.size()-1;
            cnt2++;
      }
    }
    if(cnt1>=1&&cnt2>=1) flag=1;
    if(!flag){
      cout<<-1;
      return 0;
    }
    for(int i=0;i<cnt1;i++){
      for(int j=0;j<cnt2;j++){
            if(a<b){
                if(b-a>mx) mx=b-a;
            }
      }
    }
    cout<<mx;
}

请大家帮我看看我的错误出在哪里?

陶远航 发表于 2023-10-15 10:27:19

你的代码逻辑基本上是正确的,但是在处理字符串索引和计数时存在一些问题。以下是我对你的代码的一些修改和解释:

#include <bits/stdc++.h>
using namespace std;

int a,b,cnt1,cnt2,mx=0;

int main(){
    string s,s1,s2;
    cin>>s>>s1>>s2;
    bool flag=0;
    for(int i=0;i<(int)s.size();i++){
      if(s.substr(i,s1.size())==s1){
            a=i+s1.size()-1; // 记录S1的结束位置
            cnt1++;
            i+=s1.size()-1; // 移动索引到S1的结束位置
      }
      if(s.substr(i,s2.size())==s2){
            b=i; // 记录S2的开始位置
            cnt2++;
            i+=s2.size()-1; // 移动索引到S2的结束位置
      }
    }
    if(cnt1>=1&&cnt2>=1) flag=1;
    if(!flag){
      cout<<-1;
      return 0;
    }
    for(int i=0;i<cnt1;i++){
      for(int j=0;j<cnt2;j++){
            if(a[ i]<b){
                if(b-a[ i]-1>mx) mx=b-a[ i]-1; // 计算S1的结束位置和S2的开始位置之间的距离
            }
      }
    }
    cout<<mx;
}


主要的修改点有:

1. 在找到S1或S2后,应该将索引移动到找到的字符串的结束位置,而不是开始位置。这样可以避免重复计算同一个字符串。

2. 在记录S2的位置时,应该记录S2的开始位置,而不是结束位置。因为我们需要计算的是S1的结束位置和S2的开始位置之间的距离。

3. 在计算跨距时,应该减去1,因为我们需要的是S1的结束位置和S2的开始位置之间的字符数,而不是两个位置的差值。

希望这些修改能帮助你解决问题。
请注意,本回答来自GPT-4
如果问题已经解决,请设置最佳答案

isdkz 发表于 2023-10-15 10:26:49

您好,这里是您的代码问题分析。

您的代码中,首先使用substr函数进行子串匹配,然后记录下每个匹配的位置,最后找到满足条件的最大跨距。

首先,您的代码中,对于每个匹配到的子串,您都使用substr函数进行了一次子串的拷贝,这样会造成额外的时间和空间开销。在这里,由于只需要记录匹配到的位置,可以直接记录下该子串的起始位置,而无需进行子串的拷贝。

其次,您的代码中,对于满足条件的最大跨距的查找,使用了两个循环嵌套的方式,时间复杂度为 $O(n^2)$,当字符串长度较大时,会导致程序运行时间过长。在这里,可以使用双指针的方式进行查找,时间复杂度为 $O(n)$。

下面是代码修改后的版本:

Mike_python小 发表于 2023-10-15 10:27:15

你的代码存在一个问题:当没有满足条件的S1和S2时,需要输出-1,但是你的代码没有考虑到这种情况,所以会出现未定义错误。

修改方法:在输入之后,判断一下S1和S2是否都出现过,如果都没有出现过,则直接输出-1,结束程序。

另外,你的代码中用了substr函数,但是substr函数的时间复杂度较高,可以改用循环进行匹配。

修改后的代码如下:

球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}

Lynn_oyl 发表于 2023-10-15 10:31:39

本帖最后由 Lynn_oyl 于 2023-10-15 10:32 编辑

发错了

Lynn_oyl 发表于 2023-10-15 10:35:42

陶远航 发表于 2023-10-15 10:27
你的代码逻辑基本上是正确的,但是在处理字符串索引和计数时存在一些问题。以下是我对你的代码的一些修改和 ...

Runtime Error 2.32388ms 504KiB
ExitCode: 6 (Aborted)

terminate called after throwing an instance of 'std::out_of_range'
what():basic_string::substr: __pos (which is 18446744073709551615) > this->size() (which is 32)

Lynn_oyl 发表于 2023-10-15 10:40:11

陶远航 发表于 2023-10-15 10:27
你的代码逻辑基本上是正确的,但是在处理字符串索引和计数时存在一些问题。以下是我对你的代码的一些修改和 ...

我本地运行只读入了一个字符串(包含逗号),请问如何处理读入的问题

陶远航 发表于 2023-10-15 10:44:14

Lynn_oyl 发表于 2023-10-15 10:35


你的代码中,你使用了 cin >> s >> s1 >> s2; 来读取输入。这种方式默认是以空格作为分隔符的,所以如果你的输入是以逗号分隔的,那么你需要使用其他的方式来读取输入。

你可以使用 getline 函数来读取一整行,然后使用 stringstream 或者其他方式来分割字符串。以下是一个示例:

#include <bits/stdc++.h>
using namespace std;

int a,b,cnt1,cnt2,mx=0;

int main(){
    string line;
    getline(cin, line); // 读取一整行
    stringstream ss(line);
    string s,s1,s2;
    getline(ss, s, ','); // 使用逗号作为分隔符来分割字符串
    getline(ss, s1, ',');
    getline(ss, s2, ',');
    bool flag=0;
    for(int i=0;i<(int)s.size();i++){
      if(s.substr(i,s1.size())==s1){
            a=i+s1.size()-1; // 记录S1的结束位置
            cnt1++;
            i+=s1.size()-1; // 移动索引到S1的结束位置
      }
      if(s.substr(i,s2.size())==s2){
            b=i; // 记录S2的开始位置
            cnt2++;
            i+=s2.size()-1; // 移动索引到S2的结束位置
      }
    }
    if(cnt1>=1&&cnt2>=1) flag=1;
    if(!flag){
      cout<<-1;
      return 0;
    }
    for(int i=0;i<cnt1;i++){
      for(int j=0;j<cnt2;j++){
            if(a<b){
                if(b-a-1>mx) mx=b-a-1; // 计算S1的结束位置和S2的开始位置之间的距离
            }
      }
    }
    cout<<mx;
}
这样,你的代码就可以正确地读取以逗号分隔的输入了。
页: [1]
查看完整版本: C++题目求助3