After looking at the two strings and thinking about this for a bit I've done this procedure in my head and now I'm going to translate it into steps.
String 1: ABCDE512ABC361EG51D // S1
String 2: ADE5AHDW4131EG1DG5C // S2
When I was thinking about this we can compare characters and or substrings from S1 to S2 while keeping track of occurrences.
S1[0] = 'A' compare S2[0] = 'A' = true : found A in S2 at location 0
S1[0] = 'A' compare S2[1] = 'D' = false
S1[0] = 'A' compare S2[2] = 'E' = false
S1[0] = 'A' compare S2[3] = '5' = false
S1[0] = 'A' compare S2[4] = 'A' = true : found A in S2 at location 4
S1[0] = 'A' compare S2[5] = 'H' = false
S1[0] = 'A' compare S2[6] = 'D' = false
S1[0] = 'A' compare S2[7] = 'W' = false
S1[0] = 'A' compare S2[8] = '4' = false
S1[0] = 'A' compare S2[9] = '1' = false
S1[0] = 'A' compare S2[10] = '3' = false
S1[0] = 'A' compare S2[11] = '1' = false;
S1[0] = 'A' compare S2[12] = 'E' = false;
S1[0] = 'A' compare S2[13] = 'G' = false;
S1[0] = 'A' compare S2[14] = '1' = false;
S1[0] = 'A' compare S2[15] = 'D' = false;
S1[0] = 'A' compare S2[16] = 'G' = false;
S1[0] = 'A' compare S2[17] = '5' = false;
S1[0] = 'A' compare S2[18] = 'C' = false;
// End of First Search - Occurrences of 'A' in S2 is 2 at locations {0,4}
// Next Iteration
String 1: ABCDE512ABC361EG51D // S1
String 2: ADE5AHDW4131EG1DG5C // S2
// Repeat this for all single characters Of S1 against S2
'A' in S2 = 2 at {0,4}
'B' in S2 = 0
'C' in S2 = 1 at {18}
'D' in S2 = 3 at {1,6,15}
'E' in S2 = 2 at {2,12}
'5' in S2 = 2 at {3,17}
'1' in S2 = 3 at {9,11,14}
'2' in S2 = 0
'A' Already Found Above Skip
'B' Already Found Above Skip
'C' Already Found Above Skip
'3' in S2 = 1 at {10}
'6' in S2 = 0
'1' Already Found Above Skip
'E' Already Found Above Skip
'G' in S2 = 2 at {13, 16}
'5' Already Found Above Skip
'1' Already Found Above Skip
'D' Already Found Above Skip
This would conclude the first set of iterations for doing all single characters and as you can see we also built a list and a map or sets of not only occurrences but also their locations and we can store them for future references. So if we begin to search for S1[0 & 1] in S2 we know that S1[1] does not exist in S2 so we can break and don't need to go down that chain and since we can break out of that branch we can also skip over doing S1[1 & ...N] and move directly to S1[2] and we know that there is only 1 occurrence of S1[2] which is 'C' in S2 located at {18} which is the end of the string so there is no need to look for S1[2 & ... N] so we can skip over this and move to S1[3] which is 'D' and we know that it does exist in S2 at {1,6,15} so now we can begin our search of S1[3 & ... N] beginning with S2[1 & ... N] then again do the same search of S1[3 & ... N] starting at S2[6 & ... N] and finally again starting S2[15 & ...N] then we have now found all sub strings that start with D in S2 and we can save their occurrences; however this is were we do want to find the longest substring between the two. The longest sub string is "DE5" and there is only one occurrence of it, but from this we have also already found the sub strings "DE" & "E5" so we can search for them at this point as well and we then find that there are 1 occurrence of each. And we just repeat this process. It will take sort of a long time at first, but the more you traverse through the strings, the faster it will work because of eliminating already found occurrences as well as skipping over non found sub strings of S1 in S2.
This is the logical approach that I took without using any code or programming semantics for it is just the basic algorithm of doing this logically. It now becomes a matter of determination to put this into functions and containers to write a source code implementation of it.
EDIT - As asked in the comments about the difference of this versus another's answer and with the time & space complexity here is a version of my algorithm doing the first pass searching for single characters and creating the tables of positions and if they exist in the 2nd string. The stored vector in the class contains each unique character in S1 within S2. This can then be used to help find longer substrings.
// C++ - The user asked for this in C but I haven't used C in nearly 10 years so this is my version of it in C++ :(
#include <string>
#include <vector>
class SubStringSearch {
private:
std::string S1;
std::string S2;
struct SubstringResult {
std::string substring;
bool found;
std::vector<unsigned> positions;
SubstringResult(){}
SubstringResult( const std::string& substringIn, bool foundIn, std::vector<unsigned> positionsIn ) :
substring( substringIn ), found( foundIn ), positions( positionsIn ) {}
};
std::vector<SubstringResult> results;
public:
SubStringSearch( const std::string& s1, const std::string& s2 ) : S1( s1 ), S2( s2 ) {}
void compareStringsFirstPass();
std::vector<unsigned> findLocations( const std::string& str, char findIt );
void printResults() const;
};
std::vector<unsigned> SubStringSearch::findLocations( const std::string& str, char findIt ) {
std::vector<unsigned> locations;
for ( unsigned i = 0; i < str.size(); ++i ) {
if ( str[i] == findIt ) {
locations.push_back( i );
}
}
return locations;
}
void SubStringSearch::compareStringsFirstPass() {
std::vector<unsigned> positions;
std::string sub;
bool alreadyFound = false;
for ( unsigned idx = 0; idx < S1.size(); ++idx ) {
sub = S1[idx];
if ( idx > 0 ) {
for ( unsigned u = 0; u < results.size(); ++u ) {
if ( sub == results[u].substring ) {
alreadyFound = true;
break;
}
}
}
// Added An If Else Here To Reduce Unneeded Calls To findLocations()
if ( alreadyFound ) {
alreadyFound = false;
continue;
} else {
positions = findLocations( S2, S1[idx] );
}
if ( positions.size() > 0 && !alreadyFound ) {
results.push_back( SubstringResult( sub, true, positions ) );
} else if ( !alreadyFound ) {
positions.clear();
results.push_back( SubstringResult( sub, false, positions ) );
}
positions.clear();
alreadyFound = false;
}
}
void SubStringSearch::printResults() const {
for ( unsigned u = 0; u < results.size(); ++u ) {
if ( results[u].found ) {
std::cout << results[u].substring << " found in S2 at " << std::setw(2);
for ( unsigned i = 0; i < results[u].positions.size(); ++i ) {
std::cout << std::setw(2) << results[u].positions[i] << " ";
}
std::cout << std::endl;
}
}
}
int main() {
std::string S1( "ABCDE512ABC361EG51D" );
std::string S2( "ADE5AHDW4131EG1DG5C" );
SubStringSearch searchStrings( S1, S2 );
searchStrings.compareStringsFirstPass();
std::cout << "break point";
return 0;
} // main
Place a break point on that last print line and go into your debugger for either your locals or your autos in MSVC or something equivalent for your version of your compiler / debugger and check out the contents of the class's member variable that is a std::vector and you will see the character from S1 and attached to it will be a bool flag if it is found or not as well as a std::vector for each of the positions. So if the flag is false then the vector size should be 0 and vise versa if the vector size is > 0 then the flag should be true; also the size of the vector of positions is also the count or the occurrences of that character in the 2nd string which makes this nice because we don't have to calculate anything else we can just get that from the vector itself.
Now this is not the complete or full algorithm as this is only the first pass of doing each single character of string 1 and looking into string 2 while building the needed table and skipping over contents that have already been found. It will be up to the OP to build upon this if they so choose to complete the rest of the algorithm. If I happen to find some free time in the near future I may go ahead and complete the full algorithm.