C++ Merge Overlapping Strings - c++

Let's say that I have string A: "info_mesh", and I want to add it string B: "mesh_foo".
However, I want string "info_mesh_foo", not string "info_meshmesh_foo".
I can't just say:
std::string A = "randomstuffoverlap", B = "overlapwithmorestuff"
std::string C = A + B;
Because I would end up with:
C = "randomstuffoverlapoverlapwithmorestuff",
when I want:
C = "randomstuffoverlapwithmorestuff"
without the "overlap" mentioned twice, as if the created string had a "mesh" of two strings.
However, I also would want this to work if:
std::string A = "juststuff", B = "unrelatedstuff", C;
//std::string C should be made equal to "juststuffunrelatedstuff".
(so there is No shared substring between them)
How would I go about doing this?
Thanks in advance.

Try this;
std::string A = "randomstuffoverlap", B = "overlapwithmorestuff", C;
size_t pos = A.find_last_of(B[0]);
if (pos != std::string::npos)
{
std::string::difference_type d = A.size() - pos;
if (A.substr(pos) == B.substr(0, d))
C = A + B.substr(d);
else
C = A + B;
}
else
C = A + B;
std::cout << C << std::endl;

Well, starting with the maximum possible (full overlap), loop down until it fits, and then return the result from overlapping them:
std::string overlap(std::string_view a, std::string_view b) {
for (auto n = std::min(a.size(), b.size());; --n) {
if (b.endswith(a.substr(0, n))) // b.substr(b.size() - n) == a.substr(0, n)
return std::string(b) + a.substr(n);
else if (a.endswith(b.substr(0, n))) // a.substr(a.size() - n) == b.substr(0, n)
return std::string(a) + b.substr(n);
}
If you cannot use C++20 std::string_view::endswith(), use the alternative in the comment.

This has taken me a while, but I have this function:
string overlapjoin(string a, string b) {
for (long long x = (b.length()<= a.length())? b.length(): a.length(); x > 0; --x)
if (a.substr(a.length() - x, a.length() - 1) == b.substr(0, x))
return(a.substr(0, a.length() - x) + b);
return(a + b);
}
Which can also be expressed as, if you want a limit to shared characters:
string overlapjoin(string a, string b, int maxlength) {
for (long long x = maxlength; x > 0; --x)
if (a.substr(a.length() - x, a.length() - 1) == b.substr(0, x))
return(a.substr(0, a.length() - x) + b);
return(a + b);
}

Related

Looking for nbit adder in c++

I was trying to build 17bit adder, when overflow occurs it should round off should appear just like int32.
eg: In int32 add, If a = 2^31 -1
int res = a+1
res= -2^31-1
Code I tried, this is not working & is there a better way. Do I need to convert decimal to binary & then perform 17bit operation
int addOvf(int32_t result, int32_t a, int32_t b)
{
int max = (-(0x01<<16))
int min = ((0x01<<16) -1)
int range_17bit = (0x01<<17);
if (a >= 0 && b >= 0 && (a > max - b)) {
printf("...OVERFLOW.........a=%0d b=%0d",a,b);
}
else if (a < 0 && b < 0 && (a < min - b)) {
printf("...UNDERFLOW.........a=%0d b=%0d",a,b);
}
result = a+b;
if(result<min) {
while(result<min){ result=result + range_17bit; }
}
else if(result>min){
while(result>max){ result=result - range_17bit; }
}
return result;
}
int main()
{
int32_t res,x,y;
x=-65536;
y=-1;
res =addOvf(res,x,y);
printf("Value of x=%0d y=%0d res=%0d",x,y,res);
return 0;
}
You have your constants for max/min int17 reversed and off by one. They should be
max_int17 = (1 << 16) - 1 = 65535
and
min_int17 = -(1 << 16) = -65536.
Then I believe that max_int_n + m == min_int_n + (m-1) and min_int_n - m == max_int_n - (m-1), where n is the bit count and m is some integer in [min_int_n, ... ,max_int_n]. So putting that all together the function to treat two int32's as though they are int17's and add them would be like
int32_t add_as_int17(int32_t a, int32_t b) {
static const int32_t max_int17 = (1 << 16) - 1;
static const int32_t min_int17 = -(1 << 16);
auto sum = a + b;
if (sum < min_int17) {
auto m = min_int17 - sum;
return max_int17 - (m - 1);
} else if (sum > max_int17) {
auto m = sum - max_int17;
return min_int17 + (m - 1);
}
return sum;
}
There is probably some more clever way to do that but I believe the above is correct, assuming I understand what you want.

C++ exit code 3221225725, Karatsuba multiplication recursive algorithm

The Karatsuba multiplication algorithm implementation does not output any result and exits with code=3221225725.
Here is the message displayed on the terminal:
[Running] cd "d:\algorithms_cpp\" && g++ karatsube_mul.cpp -o karatsube_mul && "d:\algorithms_cpp\"karatsube_mul
[Done] exited with code=3221225725 in 1.941 seconds
Here is the code:
#include <bits/stdc++.h>
using namespace std;
string kara_mul(string n, string m)
{
int len_n = n.size();
int len_m = m.size();
if (len_n == 1 && len_m == 1)
{
return to_string((stol(n) * stol(m)));
}
string a = n.substr(0, len_n / 2);
string b = n.substr(len_n / 2);
string c = m.substr(0, len_m / 2);
string d = m.substr(len_m / 2);
string p1 = kara_mul(a, c);
string p2 = kara_mul(b, d);
string p3 = to_string((stol(kara_mul(a + b, c + d)) - stol(p1) - stol(p2)));
return to_string((stol(p1 + string(len_n, '0')) + stol(p2) + stol(p3 + string(len_n / 2, '0'))));
}
int main()
{
cout << kara_mul("15", "12") << "\n";
return 0;
}
And after fixing this I would also like to know how to multiply two 664 digit integers using this technique.
There are several issues:
The exception you got is caused by infinite recursion at this call:
kara_mul(a + b, c + d)
As these variables are strings, the + is a string concatenation. This means these arguments evaluate to
n and m, which were the arguments to the current execution of the function.
The correct algorithm would perform a numerical addition here, for which you need to provide an implementation (adding two string representations of potentially very long integers)
if (len_n == 1 && len_m == 1) detects the base case, but the base case should kick in when either of these sizes is 1, not necessary both. So this should be an || operator, or should be written as two separate if statements.
The input strings should be split such that b and d are equal in size. This is not what your code does. Note how the Wikipedia article stresses this point:
The second argument of the split_at function specifies the number of digits to extract from the right
stol should never be called on strings that could potentially be too long for conversion to long. So for example, stol(p1) is not safe, as p1 could have 20 or more digits.
As a consequence of the previous point, you'll need to implement functions that add or subtract two string representations of numbers, and also one that can multiply a string representation with a single digit (the base case).
Here is an implementation that corrects these issues:
#include <iostream>
#include <algorithm>
int digit(std::string n, int i) {
return i >= n.size() ? 0 : n[n.size() - i - 1] - '0';
}
std::string add(std::string n, std::string m) {
int len = std::max(n.size(), m.size());
std::string result;
int carry = 0;
for (int i = 0; i < len; i++) {
int sum = digit(n, i) + digit(m, i) + carry;
result += (char) (sum % 10 + '0');
carry = sum >= 10;
}
if (carry) result += '1';
reverse(result.begin(), result.end());
return result;
}
std::string subtract(std::string n, std::string m) {
int len = n.size();
if (m.size() > len) throw std::invalid_argument("subtraction overflow");
if (n == m) return "0";
std::string result;
int carry = 0;
for (int i = 0; i < len; i++) {
int diff = digit(n, i) - digit(m, i) - carry;
carry = diff < 0;
result += (char) (diff + carry * 10 + '0');
}
if (carry) throw std::invalid_argument("subtraction overflow");
result.erase(result.find_last_not_of('0') + 1);
reverse(result.begin(), result.end());
return result;
}
std::string simple_mul(std::string n, int coefficient) {
if (coefficient < 2) return coefficient ? n : "0";
std::string result = simple_mul(add(n, n), coefficient / 2);
return coefficient % 2 ? add(result, n) : result;
}
std::string kara_mul(std::string n, std::string m) {
int len_n = n.size();
int len_m = m.size();
if (len_n == 1) return simple_mul(m, digit(n, 0));
if (len_m == 1) return simple_mul(n, digit(m, 0));
int len_min2 = std::min(len_n, len_m) / 2;
std::string a = n.substr(0, len_n - len_min2);
std::string b = n.substr(len_n - len_min2);
std::string c = m.substr(0, len_m - len_min2);
std::string d = m.substr(len_m - len_min2);
std::string p1 = kara_mul(a, c);
std::string p2 = kara_mul(b, d);
std::string p3 = subtract(kara_mul(add(a, b), add(c, d)), add(p1, p2));
return add(add(p1 + std::string(len_min2*2, '0'), p2), p3 + std::string(len_min2, '0'));
}

Input 300 000 sets of numbers with cin or scanf

Hi,
I am participating in programming contest. My algorithm is fine with number of sets to 5000.
Sets of values are consist of three integers.
But I enter 300 000 sets of numbers, it takes too long.
Limit of running program: 14s.
Fetching data: 576s. (Way too long)
My formatted input is:
300000
a b c
300000 - number of sets
a, b, c - elements of the set
My algorithm (dont judge about the code):
#include <iostream>
using namespace std;
int min_replacements(int n, int *ds, int *ps, int *rs);
int max(int a, int b, int c);
bool ot(int a, int b, int c);
bool ooo(int a, int b, int c);
bool to(int a, int b, int c);
int main()
{
int n = 0;
cin >> n;
int *ds, *ps, *rs;
ds = new int[n];
ps = new int[n];
rs = new int[n];
int d{}, p{}, r{};
for (int i = 0; i < n; i++)
{
scanf("%d %d %d", &ds[i], &ps[i], &rs[i]);
printf("%d", i);
}
int t = min_replacements(n, ds, ps, rs);
printf("%d\n", t);
delete[] ds;
delete[] ps;
delete[] rs;
}
bool ot(int a, int b, int c)
{
return (a != 0 && b == 0 && c == 0);
}
bool ooo(int a, int b, int c)
{
return (a == 0 && b != 0 && c == 0);
}
bool to(int a, int b, int c)
{
return (a == 0 && b == 0 && c != 0);
}
int max(int a, int b, int c)
{
int m = 0;
if (a == b && c < a)
{
m = a;
}
if (b == c && a < b)
{
m = b;
}
if (a == c && b < c)
{
m = c;
}
if (b < a && c < a)
{
m = a;
}
if (a < b && c < b)
{
m = b;
}
if (a < c && b < c)
{
m = c;
}
if (a == b && b == c)
{
m = a;
}
return m;
}
int min_replacements(int n, int *ds, int *ps, int *rs)
{
int t = 0;
if (ds[0] == ps[0] && ps[0] == rs[0] && ds[0] == rs[0])
{
return (n + ps[0]) * rs[0];
}
bool loop = true;
while (loop)
{
for (int i = 0; i < n - 1; ++i)
{
if (ot(*(ds + i), *(ps + i), *(rs + i)) || ooo(*(ds + i), *(ps + i), *(rs + i)) || to(*(ds + i), *(ps + i), *(rs + i)))
{
continue;
}
int m = max(*(ds + i), *(ps + i), *(rs + i));
if (m == *(ds + i))
{
*(ps + i + 1) += *(ps + i);
*(rs + i + 1) += *(rs + i);
*(ps + i) = *(rs + i) = 0;
t += 2;
}
if (m == *(ps + i))
{
*(ds + i + 1) += *(ds + i);
*(rs + i + 1) += *(rs + i);
*(ds + i) = *(rs + i) = 0;
t += 2;
}
if (m == *(rs + i))
{
*(ds + i + 1) += *(ds + i);
*(ps + i + 1) += *(ps + i);
*(ps + i) = *(ds + i) = 0;
t += 2;
}
}
for (int i = 0; i < n; ++i)
{
if (ot(*(ds + i), *(ps + i), *(rs + i)) || ooo(*(ds + i), *(ps + i), *(rs + i)) || to(*(ds + i), *(ps + i), *(rs + i)))
{
loop = false;
}
else
{
loop = true;
}
}
if (loop)
{
*ds += *(ds + n - 1);
*ps += *(ps + n - 1);
*rs += *(rs + n - 1);
*(ds + n - 1) = *(ps + n - 1) = *(rs + n - 1) = 0;
t -= 2;
}
}
if (t == 0)
return 0;
return t + 1;
}
I used a cin in this algorithm
Can you help me? Thank you so much.
How do you know the std::cin part is the problem? Did you profile your code? If not, I suggest doing that, it's often surprising which part of the code is taking up most time. See e.g. How can I profile C++ code running on Linux?.
You're doing a lot of unnecessary work in various parts of the code. For example, your max function does at least 7 comparissons, and looks extremely error prone to write. You could simply replace the whole function by:
std::max({ a, b, c })
I would also take a look at your min_replacements function and see if it can be simplified. Unfortunately, you're using variable names which are super vague, so it's pretty much impossible to understand what the code should be doing. I suggest using much more descriptive variable names. That way the code will become much easier to reason about. The way it's currently written, there's a very good change even you yourself won't be able to make sense of it in a month's time.
Just glacing over the min_replacements function though, there's definitely a lot more work going on than necessary. E.g. the last for-loop:
for (int i = 0; i < n; ++i)
{
if (ot(*(ds + i), *(ps + i), *(rs + i)) || ooo(*(ds + i), *(ps + i), *(rs + i)) || to(*(ds + i), *(ps + i), *(rs + i)))
{
loop = false;
}
else
{
loop = true;
}
}
Each loop iterator sets the loop variable. Assuming this code is correct, you don't need the loop at all, just do the check only once for i = n - 1. That's already O(n) changed to O(1).

Adding negative and positive numbers up to 10^100000

I've been trying to solve this problem (from school) for just about a week now. We're given two numbers, from -(10^100000) to +that.
Of course the simplest solution is to implement written addition, so that's what I did. I decided, that I would store the numbers as strings, using two functions:
int ti(char a) { // changes char to int
int output = a - 48;
return output;
}
char tc(int a) { // changes int to char
char output = a + 48;
return output;
}
This way I can store negative digits, like -2. With that in mind I implemented a toMinus function:
void toMinus(std::string &a) { // 123 -> -1 -2 -3
for (auto &x : a) {
x = tc(-ti(x));
}
}
I also created a changeSize function, which adds 0 to the beginning of the number until they are both their max size + 1 and removeZeros, which removes leading zeros:
void changeSize(std::string &a, std::string &b) {
size_t exp_size = std::max(a.size(), b.size()) + 2;
while (a.size() != exp_size) {
a = '0' + a;
}
while (b.size() != exp_size) {
b = '0' + b;
}
}
void removeZeros(std::string &a) {
int i = 0;
for (; i < a.size(); i++) {
if (a[i] != '0') {
break;
}
}
a.erase(0, i);
if (a.size() == 0) {
a = "0";
}
}
After all that, I created the main add() function:
std::string add(std::string &a, std::string &b) {
bool neg[2] = {false, false};
bool out_negative = false;
if (a[0] == '-') {
neg[0] = true;
a.erase(0, 1);
}
if (b[0] == '-') {
neg[1] = true;
b.erase(0, 1);
}
changeSize(a, b);
if (neg[0] && !(neg[1] && neg[0])) {
toMinus(a);
}
if(neg[1] && !(neg[1] && neg[0])) {
toMinus(b);
}
if (neg[1] && neg[0]) {
out_negative = true;
}
// Addition
for (int i = a.size() - 1; i > 0; i--) {
int _a = ti(a[i]);
int _b = ti(b[i]);
int out = _a + _b;
if (out >= 10) {
a[i - 1] += out / 10;
} else if (out < 0) {
if (abs(out) < 10) {
a[i - 1]--;
} else {
a[i - 1] += abs(out) / 10;
}
if (i != 1)
out += 10;
}
a[i] = tc(abs(out % 10));
}
if (ti(a[0]) == -1) { // Overflow
out_negative = true;
a[0] = '0';
a[1]--;
for (int i = 2; i < a.size(); i++) {
if (i == a.size() - 1) {
a[i] = tc(10 - ti(a[i]));
} else {
a[i] = tc(9 - ti(a[i]));
}
}
}
if (neg[0] && neg[1]) {
out_negative = true;
}
removeZeros(a);
if (out_negative) {
a = '-' + a;
}
return a;
}
This program works in most cases, although our school checker found that it doesn't - like instead of
-4400547114413430129608370706728634555709161366260921095898099024156859909714382493551072616612065064
it returned
-4400547114413430129608370706728634555709161366260921095698099024156859909714382493551072616612065064
I can't find what the problem is. Please help and thank you in advance.
Full code on pastebin
While I think your overall approach is totally reasonable for this problem, your implementation seems a bit too complicated. Trying to solve this myself, I came up with this:
#include <iostream>
#include <limits>
#include <random>
#include <string>
bool greater(const std::string& a, const std::string& b)
{
if (a.length() == b.length()) return a > b;
return a.length() > b.length();
}
std::string add(std::string a, std::string b)
{
std::string out;
bool aNeg = a[0] == '-';
if (aNeg) a.erase(0, 1);
bool bNeg = b[0] == '-';
if (bNeg) b.erase(0, 1);
bool resNeg = aNeg && bNeg;
if (aNeg ^ bNeg && (aNeg && greater(a, b) || bNeg && greater(b, a)))
{
resNeg = true;
std::swap(a, b);
}
int i = a.length() - 1;
int j = b.length() - 1;
int carry = 0;
while (i >= 0 || j >= 0)
{
const int digitA = (i >= 0) ? a[i] - '0' : 0;
const int digitB = (j >= 0) ? b[j] - '0' : 0;
const int sum = (aNeg == bNeg ? digitA + digitB : (bNeg ? digitA - digitB : digitB - digitA)) + carry;
carry = 0;
if (sum >= 10) carry = 1;
else if (sum < 0) carry = -1;
out = std::to_string((sum + 20) % 10) + out;
i--;
j--;
}
if (carry) out = '1' + out;
while (out[0] == '0') out.erase(0, 1);
if (resNeg) out = '-' + out;
return out;
}
void test()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(-std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max());
for (int i = 0; i < 1000000; ++i)
{
const int64_t a = dis(gen);
const int64_t b = dis(gen);
const auto expected = std::to_string(a + b);
const auto actual = add(std::to_string(a), std::to_string(b));
if (actual != expected) {
std::cout << "mismatch expected: " << expected << std::endl;
std::cout << "mismatch actual : " << actual << std::endl;
std::cout << " a: " << a << std::endl;
std::cout << " b: " << b << std::endl;
}
}
}
int main()
{
test();
}
It can potentially be further optimized, but the main points are:
If the sign of both numbers is the same, we can do simple written addition. If both are negative, we simply prepend - at the end.
If the signs are different, we do written subtraction. If the minuend is greater than the subtrahend, there's no issue, we know that the result will be positive. If, however, the subtrahend is greater, we have to reformulate the problem. For example, 123 - 234 we would formulate as -(234 - 123). The inner part we can solve using regular written subtraction, after which we prepend -.
I test this with random numbers for which we can calculate the correct result using regular integer arithmetic. Since it doesn't fail for those, I'm pretty confident it also works correctly for larger inputs. An approach like this could also help you uncover cases where your implementation fails.
Other than that, I think you should use a known failing case with a debugger or simply print statements for the intermediate steps to see where it fails. The only small differences in the failing example you posted could point at some issue with handling a carry-over.

Min Unique Characters

REF: Ques 5 on this link: http://www.geeksforgeeks.org/directi-programming-questions
Given: two strings X and Y , with only one operation possible i.e swap the corresponding letters of X and Y ( i.e. X[i] and Y[i] ) which can be performed any number of times.
n(X) : number of unique characters in X
n(Y) : number of unique characters in Y
Problem : By Using the swap operations , Find the minimum possible values of max(n(X),n(Y))
INPUT:
ababa
babab
OUTPUT:
1
--------------------
INPUT:
abaaa
baaac
OUTPUT:
2
Please help me correct my solution or solve this problem with a better approach.
My Approach (Works For first and many other testcases but not the second one ) :
for(int i=0; i<x;i++)
{
if((count1[st1[i]]!=-1)||(count2[st2[i]]!=-1))
{
if(st1[i]!=st2[i])
{
if(count1[st1[i]]!=-1)
count1[st1[i]]++;
if(count2[st2[i]]!=-1)
count2[st2[i]]++;
}
else
{
ans++;
count1[st1[i]]=-1;
count2[st1[i]]=-1;
}
}
}
for(int i=97;i<123;i++)
{
if(count1[i]>0)
c1++;
if(count2[i]>0)
c2++;
if((count1[i]>0)&&(count2[i]>0))
com++;
}
un = max(c1,c2);
ans+= un-com/2;
printf("%lld\n",ans);
I'm not sure that I understood your algorithm, but here is brute-force version, which works for strings up-to 64 symbols length:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define max(a,b) (a >= b ? a : b)
#define min(a, b) (a <= b ? a : b)
#define swap(a, b, idx) (a[idx] = a[idx] ^ b[idx] ^ (b[idx] = a[idx]))
int unique(char*a) {
char c[256] = { 0 };
int u = 0;
while (*a) {
u += (c[*a] == 0);
c[*a++] = 1;
}
return u;
}
void swapWithMask(char* a, char* b, unsigned long int mask, int l) {
for (int j = 0; j < l; j++)
if ((mask & (1 << j)) != 0)
swap(a, b, j);
}
int minUnique(char*oa, char*ob) {
int l = strlen(oa);
int minu = l;
char *a = malloc(l + 1);
strcpy(a, oa);
char *b = malloc(l + 1);
strcpy(b, ob);
unsigned long int m = (1 << l);
for (unsigned long int i = 0; i < m; i++) {
swapWithMask(a, b, i, l);
minu = min(max(unique(a), unique(b)), minu);
swapWithMask(a, b, i, l);
}
free(b);
free(a);
return minu;
}
int main(void) {
puts((minUnique("directi", "itcerid") == 4) ? "ok" : "fail");
puts((minUnique("ababa", "babab") == 1) ? "ok" : "fail");
puts((minUnique("abaaa", "baabb") == 2) ? "ok" : "fail");
return 0;
}