题目要求:找到一个字符串中的一个连续子串,这个子串内不能有任何两个字符是相同的,并且这个子串是符合要求的最长的。
例如:abcdeab,这个字符串有很多不重复子串,比如:abcde, bcdea, cdeab都是不重复子串,而且都是最长的。
这个是一个经典的笔试题,百度也曾经出过。
下面是代码:(注:由于我的代码本来目的是只求出长度即可,所以只保留了最后一个最长串的结果;如果想求得所有最长的不重复子串,即把所有可能都列出来,则需要再遍历一遍数组或者把所有结果保存下来,需要对代码作修改)
PS:我在代码中用了hash_map,估计要比较新版的VC才支持,我不知道GCC或者G++需要把命名空间改为什么,请读者自行修改代码。
#include <iostream>
#include <string>
#include <hash_map>
using namespace std;
using namespace stdext;
//acronym : LNS
pair<string, size_t> longest_norepeat_substring( string& str )
{
hash_map<char, int> char_index;//save the character and last postion it appears
size_t currentStart = 0;//start position of the LNS
size_t repeated_postion = 0;//the last postion of the repeated character
size_t maxLength = 0;//max length of the LNS
size_t curLength = 0;//current LNS length
size_t finalStart = 0;
//O(N) traverse
for( size_t i = 0 ; i < str.size() ; i++ )
{
if( char_index.find( str[i] ) != char_index.end() ) //repeated character
{
char repeatChar = str[i];
//if the repeated position is behind the current start position
//change the current start postion of LNS
repeated_postion = char_index[repeatChar];
if( repeated_postion + 1 > currentStart )
currentStart = repeated_postion + 1;
//also change the current LNS length
curLength = i - currentStart + 1;
//update the last appearance of the repeated character
char_index[repeatChar] = i;
}
else//not repeated character
{
char_index.insert( pair<char, int>( str[i], i ) );
curLength++;
//update the max LNS length
if( curLength > maxLength )
maxLength = curLength;
//remember the start position of final result
finalStart = currentStart;
}
}
return pair<string, size_t>( str.substr( finalStart, maxLength ), maxLength );
}
#include <string>
#include <hash_map>
using namespace std;
using namespace stdext;
//acronym : LNS
pair<string, size_t> longest_norepeat_substring( string& str )
{
hash_map<char, int> char_index;//save the character and last postion it appears
size_t currentStart = 0;//start position of the LNS
size_t repeated_postion = 0;//the last postion of the repeated character
size_t maxLength = 0;//max length of the LNS
size_t curLength = 0;//current LNS length
size_t finalStart = 0;
//O(N) traverse
for( size_t i = 0 ; i < str.size() ; i++ )
{
if( char_index.find( str[i] ) != char_index.end() ) //repeated character
{
char repeatChar = str[i];
//if the repeated position is behind the current start position
//change the current start postion of LNS
repeated_postion = char_index[repeatChar];
if( repeated_postion + 1 > currentStart )
currentStart = repeated_postion + 1;
//also change the current LNS length
curLength = i - currentStart + 1;
//update the last appearance of the repeated character
char_index[repeatChar] = i;
}
else//not repeated character
{
char_index.insert( pair<char, int>( str[i], i ) );
curLength++;
//update the max LNS length
if( curLength > maxLength )
maxLength = curLength;
//remember the start position of final result
finalStart = currentStart;
}
}
return pair<string, size_t>( str.substr( finalStart, maxLength ), maxLength );
}
下面是测试的例子:
int main()
{
string str = "abcdeab";
cout<<longest_norepeat_substring( str ).first<<endl;
cout<<longest_norepeat_substring( str ).second<<endl;
string s = "happybirthdayob";
cout<<longest_norepeat_substring( s ).first<<endl;
cout<<longest_norepeat_substring( s ).second<<endl;
}
{
string str = "abcdeab";
cout<<longest_norepeat_substring( str ).first<<endl;
cout<<longest_norepeat_substring( str ).second<<endl;
string s = "happybirthdayob";
cout<<longest_norepeat_substring( s ).first<<endl;
cout<<longest_norepeat_substring( s ).second<<endl;
}
附:这里有一个CSDN的讨论:
http://topic.csdn.net/u/20090726/22/8b3f9f3a-5bad-4035-abd8-46b2231e83b0.html