I posted my question couple days ago while i was still working on my code. I will restate my question so it would be clear for everyone.
Goal: print All of the Unicodes available using a loop.
Question: why I can only print them, as symbols, if they were hardcoded in a string rather then a variable.
Output:
U000000
U000001
U000002
...
U000017
U000018
#include <iostream>
#include <cmath>
using namespace std;
const int HexBase=16;
const int HexMax=15;
const int UniCharMaxPrint=1000;
const int ASCCIAlphaCapBase=48;
int main() {
int DecNum = 0;
int sizeHex= 3;
for (int j=0; j < UniCharMaxPrint; j++)//prints 100 unviersal Chars
{
int DecNumCopy = DecNum;
int resultDiv =0;
string HexChar=" ";
string HexNum ="X";
string UniNum ="u";
string BackSlash = "\\";
string full="HI ";
for (int i = sizeHex; i >=0; i--)
{
//Dec calcultion
resultDiv = (DecNumCopy/(int)(pow(HexBase,i)));
DecNumCopy = DecNumCopy - ((int)(pow(HexBase,i)) * resultDiv);
if ((i==0) && (resultDiv>HexMax)){cout <<"Error # is Too large"<<endl;}//Check if the number entered is big or not
//Get the equivalente Hex charcter
if ((resultDiv >= 0)&&(resultDiv <= 9))
{ HexChar = ASCCIAlphaCapBase + resultDiv;}
else if ((resultDiv >= 10)&&(resultDiv <= 15))
{ switch (resultDiv)
{ case 10 : {HexChar='a'; break;};
case 11 : {HexChar='b'; break;};
case 12 : {HexChar='c'; break;};
case 13 : {HexChar='d'; break;};
case 14 : {HexChar='e'; break;};
case 15 : {HexChar='f'; break;};
}
}
else {HexChar='*';};
//if(i==sizeHex){full.append(UniNum);};
//Add to the result string
//HexNum.append(HexChar);
UniNum.append(HexChar);
full = BackSlash+UniNum;
}//endfor
DecNum++;
cout<< full << endl;
}
return 0;
}
Related
So I'm pretty new to c++, and this is the second program I've ever written in it. The first program was a complete mess but it worked, this program I decided to just put all in one file. My problem is, it just runs incredibly slowly. I'm pretty sure it's because of just how many characters it has to iterate through, but the requirements are that it can crack a password of a specific length with any special characters like these. Other than the number of characters it has to go through I'm not sure what, if anything, is making it run so slowly. I'm wondering if it's something I've done that is improper and making it take so long. Is this just about how fast a password cracker like this can run?
// Password Cracker.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <thread>
#include <atomic>
#include <vector>
#include <cmath>
#include <sstream>
std::string convertToString(char*, int);
void passwordBruteForcer(std::string, long long, long long);
std::atomic<bool> isPasswordFound = false;
std::string foundString;
int main()
{
// Given some count of the amount of symbols that can exist in the password
// We will calulcate how many possible passwords there are then divide work evenly between threads
// In this case the possible symbols are all ascii codes from 32 to 126
int numOfSymbols = 95;
// Declarations;
int numberOfThreads = 8;
std::string password;
std::vector<std::thread> vecOfThreads;
// Loop waits for correct user input (problem required that password length be 5, change this if you want)
while (true)
{
// Prompting user input
std::cout << "Please enter a password of length 5 \n";
std::cout << "password: ";
std::getline(std::cin, password);
if (password.length() == 5)
{
break;
}
else
{
std::cout << "Invalid password \n";
}
}
long long amountOfPossiblePasswords = pow(numOfSymbols, password.length());
// Creates threads running brute force cracker
for (int threadNumber = 1; threadNumber <= numberOfThreads; threadNumber++)
{
long long startingNumber = (amountOfPossiblePasswords * (threadNumber - 1)) / numberOfThreads;
long long endNumber = (amountOfPossiblePasswords * threadNumber) / numberOfThreads;
long long remainder = amountOfPossiblePasswords % numberOfThreads;
if (threadNumber == numberOfThreads)
{
vecOfThreads.push_back(std::thread(passwordBruteForcer, password, startingNumber, endNumber + remainder));
}
else
{
vecOfThreads.push_back(std::thread(passwordBruteForcer, password, startingNumber, endNumber));
}
}
// Wait to join thread
for (std::thread & th : vecOfThreads)
{
if (th.joinable())
th.join();
}
// Prints the password the algorithm found
if (isPasswordFound)
{
std::cout << foundString;
}
return 0;
}
// Will go through all "printable" ASCII characters
void passwordBruteForcer(std::string passStr, long long startingNumber, long long endNumber)
{
int firstChar = 32;
int lastChar = 126;
int length = passStr.length();
int numOfChar = 95;
int numOfTries = pow(numOfChar, length);
char* guess = new char[length];
// Converts decimal to base num of chars then puts that char into array
// For ex. 0 will be first char, and a 1 will be the next char, the number that represents the amount of possible passwords
// will set this to be all lastChar
long long numToBeConvert = startingNumber;
for (int i = (length - 1); i >= 0; i--)
{
guess[i] = firstChar + (numToBeConvert % numOfChar);
numToBeConvert /= numOfChar;
}
// This creates a string based on initialized guess then tests it
std::string comparisonPasswordString = convertToString(guess, length);
if (comparisonPasswordString == passStr)
{
isPasswordFound = true;
foundString = comparisonPasswordString;
delete[] guess;
return;
}
// This loop goes from startingNumber to endNumber testing all passwords
for(long long i = startingNumber; i < endNumber; i++)
{
if (isPasswordFound == true)
{
break;
}
long long numForGuess = i;
for (int j = (length - 1); j >= 0; j--)
{
guess[j] = firstChar + (numForGuess % numOfChar);
numForGuess /= numOfChar;
}
comparisonPasswordString = convertToString(guess, length);
if (comparisonPasswordString == passStr)
{
isPasswordFound = true;
foundString = comparisonPasswordString;
break;
}
}
delete[] guess;
}
std::string convertToString(char* charArr, int length)
{
std::string convString;
for (int i = 0; i < length; i++)
{
convString.push_back(charArr[i]);
}
return convString;
}
my program should have store = 5 string values - Simpsun GN120, Sonic Lux10, Ultimax G42, Antalpha A200 and Nickov N230 and then make a calculation that will make code for each value. Code would take first 3 letters and 3 last letters of a value.
first code from value: Simpsun GN120
would look like this: Sim120
my biggest issue was that i couldn't make a string array as getting a length of each value in array would crash a program so for now i have made program that will do this calculation but only if string is not array if someone could give me some tips how i could improve my code to make that string in to array
#include <iostream>
using namespace std;
int main()
{
string str = "Simpsun GN120";
int i;
string productCode[5];
for (i = 0; i < str.length(); i++)
{
if (i == 0 || i == 1 || i == 2)
{
productCode[0] += str[i];
}
if (i == str.length() - 1 || i == str.length() - 2 || i == str.length() - 3)
{
productCode[0] += str[i];
}
}
cout << productCode[0];
}
It's simple using string class .Run a loop to execute
productCode[i] = str[i].substr(0, 3) + str[i].substr(str[i].length() - 3);
and your work is done.
jignatius Thank you very much for that answer!
using namespace std;
int main()
{
string str[2] = { "Simpsun GN120", "Sonic Lux10" };
int i;
string productCode[5];
for (int i = 0; i < 2; i++)
{
productCode[i] = str[i].substr(0, 3) + str[i].substr(str[i].length() - 3);
}
cout << productCode[0] << endl;
cout << productCode[1];
}
Write a recursive function to convert a given string into the number it represents. That is input will be a numeric string that contains only numbers, you need to convert the string into corresponding integer and return the answer.
I only get the first digit of my string as the output. E.g "1234" as 1 or "231" as 2. Which makes me think there may be an error in my recursive function (the base case seems fine though) but I cant figure out what it is.
#include <math.h>
#include <cmath>
#include <iostream>
using namespace std;
int lenght (char input[]){
int count = 0;
for (int i=0 ; input[i] != '\0' ; i++){
count++;
}
return count;
}
//helper
int stringToNumber(char input[], int start ) {
int len = lenght(input);
//base case
if(start ==0){
return int (input[start]) - 48;
}
int a = stringToNumber(input , start+1);
int b = int(input[start]) - 48;
int k = pow(10, len-1);
return k*b + a;
}
int stringToNumber(char input[]) {
return stringToNumber(input, 0);
}
int main() {
char input[50];
cin >> input;
cout << stringToNumber(input) << endl;
}
Sample Input 1 :
1231
Sample Output 1:
1231
What my code generates: 1
Converting string to decimal integer - is actually converting a number from decimal to binary form. I.e. each digit is a mod of 10.
I.e. for the 1234 it can be done done like 1 * 1000 + 2 * 100 + 3 * 10 + 4
or (1*10)+2, (12*10)+3, (123*10)+4. Second algorithm can be implemented like next recursive function:
constexpr uintmax_t atou(const char* a,uintmax_t ret = 0) noexcept {
return '\0' == *a ? ret : atou(a+1, (ret * 10) + ( *a - '0') );
}
i.e. you are scanning a string for digits, until '\0' end of line character (or std::isspace for example), if more digits in the string multiply result on 10 and add the next digit to the result.
static_assert( 1234 == atou("1234"), "1234 expected" );
Try this code:
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
int convert(char c[]) {
if (c[0]=='\0') {
return 0;
} else {
int d = strlen(c) - 1;
int p = pow(10, d);
int k = int(c[0]) - 48; // ASCII value of '0' is 48
return (k * p + convert(c + 1));
}
}
int main() {
int n;
cin >> n;
char c[n];
cin >> c;
cout << convert(c);
}
public class solution {
public static int convertStringToInt(String input){
// Write your code here
if(input.length()<1)
{
return 0;
}
return input.charAt(input.length()-1)-'0'+(10*convertStringToInt(input.substring(0,input.length()-1)));
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
This a function of a code I wrote that subtracts two values which are both of type character over and over again to get a text, but the result is not a text of string but symbols instead.
I checked by cout that the keyLetters and analysis have both correct values in ASCII and clear letters before converting them to int.
The lengthText is correct too.
keyLetters is a word of 5 letters.
void originalText(string analysis, string keyLetters) {
int lengthText=analysis.length();
char originText[2000];
int hold;
int k;
for (int i=0; i<lengthText; i++) {
if(i%5==0)
k=0;
hold=keyLetters[k]-analysis[i];
if (hold<=0)
hold*=-1;
originText[i]=(char)hold;
cout<<originText[i];
k++;
}
}
A screenshot of the result I get:
Both keyLetters and analysis consist of characters between 'a' and 'z'.
That means the difference between characters in these two can be from -25 ('a' - 'z') up to +25 ('z' - 'a').
Then you want to represent this difference using ascii characters, multiplicing by -1 the negative case. Nothing simpler:
void originalText(string analysis, string keyLetters) {
int lengthText = analysis.length();
char originText[2000];
int hold;
int k;
for (int i = 0; i < lengthText; i++) {
if (i % 5 == 0) {
k = 0;
}
hold = keyLetters[k] - analysis[i];
if (hold < 0) {
hold *= -1;
}
originText[i] = (char)hold + 'a';
cout << originText[i];
k++;
}
}
You need shift the value in range <0,25> to printable small ascii characters <'a','z'> by adding a 'a' ascii value, that is 97. The range <0,25> in ascii are just control characters.
This will result in:
The decrypted text:
oncegpmnahioethejewasalihtpegirpehmwantedhoplacallthedacandihedidnmtcareabmuhhejshudcahallinschomlherlarenhsgetangjcatherallhhetimebutihedidnmtcareabmuhhejparentifeelingiwhethejthecareangrymriadiheeaisgchabadgirplehuinohbeashejnefejeverhakecaremfevejchhingarogndcogsharhingfjoocogrlarenhstilpcogshudieiatichooltakealpthatieriogslcbestmfpucknmtheshorcdmesnohfiniihherethereismojetmihthatgirlonedaceenhtmschomlwhichiiuniveriitcactualpcbgtleolletendhosacabogtitschmolhhatihiimojecommonandidonnohknmwanyeacthatgirlofcogriewenhtognivejsitymrcollegeifihavetmsacwhenihegohopdejlikeehenshebecameeighheenceariopdsmahuniversitcthereeaiapotmfitudcforhejtodoehichihehohallcicrewgpsmshecjiedandcriedalohahnighhsfhejshecamhmmeandherkindpajentsasqedhejabmuhthereasmnforhejunitmppabpeteajsthaheairgnningouhfjomhejeyesconhinuogspchmwevejsherefgsedtmtellmrsacanyhhingiinceiheeantedtmshayalmnehhatnighthereishwasfglfilledsoathhahnighhshesleltaloneinthedarqeihhmutanconebesideihejtmeahchhejandtmtakecajeofherinhersleepingasshedidhoherlajenhsanditgdiesehenshewascoungersmthecccpehasgothejrogndshapnotfrmmnmwherebgtbecauseofareaionandthatjeaionisbecauiehhingieillcomebackholeolleafhejthecdidhheminanctimeeihhmutanceajningmralejt
As to why this doesn't give the correct text, I leave that to OP, because i don't get this method of encryption.
The whole program:
#include <iostream>
#include <string>
#include <fstream>
#include <cmath>
using namespace std;
string encryptText(string, string);
string cryptanalyzeText(string);
void originalText(string, string);
int main() {
string text, analysis;
string key;
text = "onceuponatimetherewasalittlegirlwhowantedtoplayallthedayandshedidnotcareaboutherstudyatallinschoolherparentsgetangryatherallthetimebutshedidnotcareaboutherparentsfeelingswhethertheyareangryorsadshewassuchabadgirlletusnotbeasherneverevertakecareofeverythingaroundyoustartingfromyourparentstillyoustudiesatschooltakeallthatseriouslybestoflucknothestorydoesnotfinishherethereismoretoitthatgirlonedaywenttoschoolwhichisuniversityactuallybutpeopletendtosayaboutitschoolthatitismorecommonandidonnotknowanywaythatgirlofcoursewenttouniversityorcollegeifihavetosaywhenshegotolderlikewhenshebecameeighteenyearsoldsoatuniversitytherewasalotofstudyforhertodowhichshetotallyscrewupsoshecriedandcriedalotatnightsftershecamhomeandherkindparentsaskedheraboutthereasonforherunstoppabletearsthatwasrunningoutfromhereyescontinuouslyhoweversherefusedtotellorsayanythingsinceshewantedtostayalonethatnightherwishwasfulfilledsoatthatnightshesleptaloneinthedarkwithoutanyonebesideshertowatchherandtotakecareofherinhersleepingasshedidtoherparentsandstudieswhenshewasyoungersothecyclehasgotherroundshapnotfromnowherebutbecauseofareasonandthatreasonisbecausethingswillcomebacktopeopleaftertheydidtheminanytimewithoutanywarningoralert";
analysis = "qegegrfrafkdittgiiwmurpifvcigutcahayrrtqfkspxcpelxvyidmarrdejvhippfxcmtvebawkledukydkckelxkewctqfphqtgerqpkwgqvrrgdarxhqtrplfjvxiygsytejvhippfxcmtvebawkledrrvezvjjeqnzrgeyyittgixhqarvempxvyatjedejvaaeulghmdrhgutcpefwjrofdvestgirehgiivqtkekqerveahvzedaklizirvogpucogukerfkekfdqdcogtgerqpkwtunccogukydugjeteeysoxvroemncxhmvjiruqlwlkdvwtahcycwpfxhquksrkffiszqkjizkjlhqtvxhqtvmsyqiitakkxhmvxmrxqeidmaninfvfwctqfpwtktliewemvqtjmtkctxumnccbgvgiobnvxezfkssmarfogvzxsojfslfjrxifkjqodgtsmyqeenpkusnzqkonayrryicpxhmvxmrxqwgogtjiwqpkxogpzzeduzxyattslxgxiirkyevqvfwakyyinejvkofqchednzoeijvrstgsicmoviisjkiezavereqchsackynuxvvsuvpxhqtvaaeccstahjxupawsrtgixopqnliojjlefqkelxajgrqyltsauyicdkvhazftviqfrpofckrisjkwffgiwhqerqhaovenpjvvkuputadgexsmubidtgiebawkxhqtvesapwsrtgiynevftpmdcitqciwttckaaetlrnupxsufhismtgiiyqutsnfkeyogucchayvzeduyirqhlwepvfxexnfvsmarryfjzrgekegeejvaazvvhtaukeymnfrefjrxnuiyxhqtnmstyrwfgnwmlxguwomvklafpzkhfuyisxggxaxqeiizvyidmtbaifjfytmppsnqdvwipgjledvfaafeyledcehtavroeociiorjvvizjvvsxgvtizirwstgumdfqyirbciinfurrdevlhiqunlezuyiwmupsuzivvsavyickecihmuxsttgivogpuwhmrestrtfqnayyirqdlxbqerysqqwerqcjsnmpuxhmviiaeqemsngteuegklizijaixntsmqdrgkfqgiobnveffgixhqaumdfjvqizcectuovaifjfytmppaadpzrgatrpedv";
cout<<"\n1- The original text:\n"<<text;
cout<<"\n\nEnter a key of type string: ";
key = "cream";
cout<<endl;
cout<<"The text after it has been encrypted:\n"<<encryptText(text, key)<<endl;
cout<<"\n2- An encrpted text:\n"<<analysis;
string keyLetters= cryptanalyzeText(analysis);
cout<<"\n\nThe key is: "<<keyLetters<<endl<<endl;
cout<<"The decrypted text:\n";
originalText(analysis, keyLetters);
cout<<endl<<endl;;
return 0;
}
string encryptText(string text, string key) {
int lengthText=text.length();
int lengthKey=key.length();
int count=0;
for (int i=0; i<lengthText; i++) {
text[i]=key[count];
if (count<lengthKey-1)
count++;
else
count=0;
}
return text;
}
string cryptanalyzeText(string analysis) {
string keyLetters="aaaaa";
char ch;
int i;
int lengthText=analysis.length();
for (int keyPlace=0; keyPlace<6 ; keyPlace++) {
int alphabet[26]={0};
for (i=keyPlace; i<lengthText; i=i+5) {
ch=analysis[i];
alphabet[ch - 'a']++;
}
int max=alphabet[0];
int maxPlace=0;
for (int j=1; j<26; j++) {
if(max<alphabet[j]) {
max=alphabet[j];
maxPlace=j;
}
}
keyLetters[keyPlace]=maxPlace-4;
if (keyLetters[keyPlace]<0)
keyLetters[keyPlace]+=26+97;
else
keyLetters[keyPlace]+=97;
}
return keyLetters;
}
void originalText(string analysis, string keyLetters) {
int lengthText=analysis.length();
char originText[2000];
int hold;
int k;
for (int i = 0; i < lengthText; i++) {
if (i % 5 == 0) {
k=0;
}
hold = keyLetters[k] - analysis[i];
if (hold < 0) {
hold *= -1;
}
originText[i] = (char)hold + 'a';
cout << originText[i];
k++;
}
}
It appeared that since the encrypted text has been generated by %26 (mod 26), the values of the letters that was larger than 26 lost its original values. So when they have been decrypted, they were generated as incorrect letters. That's why I had to return the 26 they have lost, before doing the subtraction procedure, as it will be subtracted correctly.
void originalText(string analysis, string keyLetters) {
int lengthText=analysis.length();
char originText[2000];
int hold;
int k;
for (int i = 0; i < lengthText; i++) {
if (i % 5 == 0) {
k=0;
}
hold = (analysis[i]+26)-keyLetters[k];
if (hold < 0) {
hold *= -1;
}
hold%=26;
originText[i] = (char)hold + 'a';
cout << originText[i];
k++;
}
}
The result of it:
*Sorry about my poor English. If there is anything that you don't understand, please tell me so that I can give you more information that 'make sence'.
**This is first time asking question in Stackoverflow. I've searched some rules for asking questions correctly here, but there should be something I missed. I welcome all feedback.
I'm currently solving algorithm problems to improve my skill, and I'm struggling with one question for three days. This question is from https://algospot.com/judge/problem/read/RESTORE , but since this page is in KOREAN, I tried to translate it in English.
Question
If there are 'k' pieces of partial strings given, calculate shortest string that includes all partial strings.
All strings consist only lowercase alphabets.
If there are more than 1 result strings that satisfy all conditions with same length, choose any string.
Input
In the first line of input, number of test case 'C'(C<=50) is given.
For each test case, number of partial string 'k'(1<=k<=15) is given in the first line, and in next k lines partial strings are given.
Length of partial string is between 1 to 40.
Output
For each testcase, print shortest string that includes all partial strings.
Sample Input
3
3
geo
oji
jing
2
world
hello
3
abrac
cadabra
dabr
Sample Output
geojing
helloworld
cadabrac
And here is my code. My code seems to work perfect with Sample Inputs, and when I made test inputs for my own and tested, everything worked fine. But when I submit this code, they say my code is 'wrong'.
Please tell me what is wrong with my code. You don't need to tell me whole fixed code, I just need sample inputs that causes error with my code. Added code description to make my code easier to understand.
Code Description
Saved all input partial strings in vector 'stringParts'.
Saved current shortest string result in global variable 'answer'.
Used 'cache' array for memoization - to skip repeated function call.
Algorithm I designed to solve this problem is divided into two function -
restore() & eraseOverlapped().
restore() function calculates shortest string that includes all partial strings in 'stringParts'.
Result of resotre() is saved in 'answer'.
For restore(), there are three parameters - 'curString', 'selected' and 'last'.
'curString' stands for currently selected and overlapped string result.
'selected' stands for currently selected elements of 'stringParts'. Used bitmask to make my algorithm concise.
'last' stands for last selected element of 'stringParts' for making 'curString'.
eraseOverlapped() function does preprocessing - it deletes elements of 'stringParts' that can be completly included to other elements before executing restore().
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
string answer; // save shortest result string
vector<string> stringParts;
bool cache[MAX + 1][(1 << MAX) + 1]; //[last selected string][set of selected strings in Bitmask]
void restore(string curString, int selected=0, int last=0) {
//base case 1
if (selected == (1 << k) - 1) {
if (answer.empty() || curString.length() < answer.length())
answer = curString;
return;
}
//base case 2 - memoization
bool& ret = cache[last][selected];
if (ret != false) return;
for (int next = 0; next < k; next++) {
string checkStr = stringParts[next];
if (selected & (1 << next)) continue;
if (curString.empty())
restore(checkStr, selected + (1 << next), next + 1);
else {
int check = false;
//count max overlapping area of two strings and overlap two strings.
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size()-i, i) == checkStr.substr(0, i)) {
restore(curString + checkStr.substr(i, checkStr.length()-i), selected + (1 << next), next + 1);
check = true;
break;
}
}
if (!check) { // if there aren't any overlapping area
restore(curString + checkStr, selected + (1 << next), next + 1);
}
}
}
ret = true;
}
//check if there are strings that can be completely included by other strings, and delete that string.
void eraseOverlapped() {
//arranging string vector in ascending order of string length
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
//deleting included strings
vector<string>::iterator iter;
for (int i = 0; i < vectorLen-1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C; // testcase
for (int testCase = 0; testCase < C; testCase++) {
cin >> k; // number of partial strings
memset(cache, false, sizeof(cache)); // initializing cache to false
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
eraseOverlapped();
k = stringParts.size();
restore("");
cout << answer << endl;
answer.clear();
stringParts.clear();
}
}
After determining which string-parts can be removed from the list since they are contained in other string-parts, one way to model this problem might be as the "taxicab ripoff problem" problem (or Max TSP), where each potential length reduction by overlap is given a positive weight. Considering that the input size in the question is very small, it seems likely that they expect a near brute-force solution, with possibly some heuristic and backtracking or other form of memoization.
Thanks Everyone who tried to help me solve this problem. I actually solved this problem with few changes on my previous algorithm. These are main changes.
In my previous algorithm I saved result of restore() in global variable 'answer' since restore() didn't return anything, but in new algorithm since restore() returns mid-process answer string I no longer need to use 'answer'.
Used string type cache instead of bool type cache. I found out using bool cache for memoization in this algorithm was useless.
Deleted 'curString' parameter from restore(). Since what we only need during recursive call is one previously selected partial string, 'last' can replace role of 'curString'.
CODE
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
vector<string> stringParts;
string cache[MAX + 1][(1 << MAX) + 1];
string restore(int selected = 0, int last = -1) {
if (selected == (1 << k) - 1) {
return stringParts[last];
}
if (last == -1) {
string ret = "";
for (int next = 0; next < k; next++) {
string resultStr = restore(selected + (1 << next), next);
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
string& ret = cache[last][selected];
if (!ret.empty()) {
cout << "cache used in [" << last << "][" << selected << "]" << endl;
return ret;
}
string curString = stringParts[last];
for (int next = 0; next < k; next++) {
if (selected & (1 << next)) continue;
string checkStr = restore(selected + (1 << next), next);
int check = false;
string resultStr;
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size() - i, i) == checkStr.substr(0, i)) {
resultStr = curString + checkStr.substr(i, checkStr.length() - i);
check = true;
break;
}
}
if (!check)
resultStr = curString + checkStr;
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
void EraseOverlapped() {
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
vector<string>::iterator iter;
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C;
for (int testCase = 0; testCase < C; testCase++) {
cin >> k;
for (int i = 0; i < MAX + 1; i++) {
for (int j = 0; j < (1 << MAX) + 1; j++)
cache[i][j] = "";
}
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
EraseOverlapped();
k = stringParts.size();
string resultStr = restore();
cout << resultStr << endl;
stringParts.clear();
}
}
This algorithm is much slower than the 'ideal' algorithm that the book I'm studying suggests, but it was fast enough to pass this question's time limit.