最长的子字符串,C++中只有 2 个不同的字符
Longest substring with only 2 distinct chars in C++
我正在尝试找到最多包含 2 个不同字符的最长子字符串。它是一个蛮力程序,它只使用所有可能的子字符串并检查它们是否有 2 个或更多不同的字符。
我使用一组来跟踪不同的字符。
#include <iostream>
#include <string>
#include <algorithm>
#include <unordered_set>
using namespace std;
int main()
{
string s = "AllPossibleSubstrings";
int l=0,index=0;
for(int i =0;i<s.length();i++)
{
for(int j=i+1;j<s.length();j++)
{
string sub = string(s.begin()+i,s.begin()+j);
unordered_set<char> v;
for(auto x:sub)
{
v.insert(x);
}
if(v.size()<=2) {l=max(l,j-i+1); if(l==j-i+1) index=i;}
}
}
cout<<l<<" "+s.substr(index,l)<<endl;
}
我得到4 ssib
的错误答案,而正确答案一定没有b(All,llP,oss,ssi是可能的答案(。我哪里做错了?
调试输出添加到代码以查看它找到哪些字符串:
if(v.size()<=2) {
l=max(l,j-i+1);
if(l==j-i+1) {
index=i;
cout << "Found match " << i << " " << j << " " << l << " " << sub << endl;
}
}
你会看到它找到了正确的字符串:
Found match 0 1 2 A
Found match 0 2 3 Al
Found match 0 3 4 All
Found match 1 4 4 llP
Found match 4 7 4 oss
Found match 5 8 4 ssi
(见这里:http://ideone.com/lQqgnq(
但是你也会看到,例如,对于i=5
和j=8
你得到sub="ssi"
,但l=4
,这显然是错误的。
因此,错误行为的原因是string(s.begin()+i,s.begin()+j)
使子字符串从第 i
个字符开始,直到(但不包括(第 j
个字符:http://www.cplusplus.com/reference/string/string/string/:
template <class InputIterator> string (InputIterator first, InputIterator last);
复制范围 [first,last( 中的字符序列 相同的顺序。
请注意,不包括last
。
所以你的l
应该相应地计算:如j-i
,而不是j-i+1
。
事实上,原因是你的代码过于复杂。你在代码末尾显然使用了s.substr
,为什么不在主循环中使用相同的?你甚至可以循环i
和l
,然后你就不会有这样的问题。
此外,实际上您不需要每次都提取子字符串。您可以循环遍历i
和l
,只需保留一组不同的字符即可。这将产生更快的O(N^2)
解决方案,而您的解决方案O(N^3)
.像这样:
for (int i=0; i<s.length(); i++) {
unordered_set<char> v;
for (int l=1; l<s.length()-i; l++)
v.insert(s[i+l-1]);
if (v.size()>2) break;
if (l>maxl) {
index = i;
maxl = l;
}
}
事实上,即使是O(N)
解决方案也可以在这里实现,但需要更高级的代码。
问题是 l 变量是子字符串的长度 + 1...请注意,j 索引是子字符串最后一个字符之后的一个索引。
所以,为了正确处理它:
将 if 语句更改为:
if(v.size()<=2) {l=max(l,j-i); if(l==j-i) index=i;}
我修改了您的代码,如果我做对了,答案是找到的任何代码,如果您希望将它们存储在数组或其他东西中并显示所有相同大小(最长(。这是你能得到的尽可能多的蛮力。
#include <iostream>
#include <string>
#include <algorithm>
#include <unordered_set>
using namespace std;
int main(int args, char argv[]){
string s = "AllPossibleSubstrings";
string output = string();
int starts_from = 0, length = 0;
for (int i = 0; i < s.length(); i++){
string sub = string();
sub += s[i];
int characters = 1;
bool not_found = false;
for (int j = i + 1; j < s.length() && characters <= 2; j++){
for (int k = 0; k < sub.length(); k++)
if (s[j] != sub[k])
not_found = true;
if (not_found && characters == 1){
sub += s[j];
characters++;
}
else if (not_found && characters == 2)
break;
else
sub += s[j];
}
if (sub.length() > length){
length = sub.length();
starts_from = i; // index + 1 for the >1 value
output = sub;
}
}
cout << endl << "''" << output << "''" << " which starts from index " << starts_from << " and is " << output.length() << " characters long.." << endl;
system("pause");
return 0;
}
char* 指针比使用 String 类更容易,后者更像 Java 的方法。然后,使用与嵌套循环相同的算法结构并计算子字符串长度(从第一个到下一个大写字母(,如果它比任何其他子字符串长,则使用 char* 进行新的分配,或者创建一个新的 String 对象(如果必须使用 String 类(。当然,您从最长的值 0 开始:
unsigned int longest_substring = 0;
如果找到更大的值,正如我已经说过的,你把它更改为它的长度,然后重新分配输出字符串(char[]/char*(变量。
要使所有这些工作,您需要循环计数器,longest_string,current_string(用于在嵌套循环中检查的子字符串的长度(,当然还需要char*/String来存储到目前为止最长的子字符串。
我很着急,所以我无法提供代码,但这就是逻辑:-(
算法很好(当然,它是蛮力的,没什么花哨的(。但是,内部循环中生成的子字符串被误解了。
子字符串从索引 i 到索引 j-1(都包括在内(,它不包括索引 j。因此,子字符串的长度必须是 (j-1 - i +1( = j-1 。索引和长度变量必须使用此正确的长度进行更新。
这是错误的根源。顺便说一下,在可能的答案中,算法根据字符串中的位置返回最后一个子字符串。
也许最好重写你的代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "AllPossibleSubstrings";
int max=0,index=0;
for(int i =0;i<s.length();i++)
{
int j=i;
for(;s[j]==s[i];j++);
if((j-i+1)>max)
{
max = (j-i+1);
index = i;
}
}
cout<<max<<" "+s.substr(index,max)<<endl;
}
编辑还应该再添加一个检查。结果是循环的主体将变为这样:
int j=i+1;
for(;(s[j]==s[i] && j<n);j++);
if(j==n) break;
int z=j+1;
for(;(s[z]==s[i]||s[z]==s[j]);z++);
if((z-i)>max)
{
max = (z-i);
index = i;
}
- 从 argv[1] 转换为字符 * 字符串后有什么问题?
- 将 NULL 与 C 的字符* 字符串一起使用
- 无法在声明时使用初始值设定项列表初始化常量字符*/字符串数组的向量
- 无法将常量字符字符串传递给模板类
- 如何组合一个宽字符字符串,中间插入一些空字符
- 如何将二维数组类型字符(字符串)作为函数参数传递?
- 从给定索引返回子字符字符串的函数
- 字符 [](c 字符串)的初始化标准
- 如何将字符字符串用作数学运算符
- 将 Unicode 字符/字符串写入文件
- C++,字符* 字符串修改
- 如何有效地用不同的整数元素替换字符字符串的元素
- C++:如果我们在字符串中添加一些整数,为什么它会从开头删除该数量的字符?(字符串 + 整数)
- strcpy正在复制sth字符i字符串.如何解决此错误
- 在C++中将双精度转换为字符*/字符串
- C 中的宽字符字符串
- 如何提取C 中的字符/字符串之间的字符串
- 无法将字符/字符串转换为int
- 带有指针的反转字符字符串
- 反转字符串中的 n 个字符(字符串中没有空格),而不使用 c++ 中的内置函数