Find substring in string from the end - c++

I need to find position of string in substring. Scan has to begin from the end. For example:
findch(L"asdhuifdsahdfasasd", L"asd");
return 16 instead of 1
Here is my function:
int findchr(LPCWSTR T, LPCWSTR P)
{
int n = lstrlenW(T);
int m = lstrlenW(P);
for (int i = 0; i <= n - m; ++i) {
int j = 0;
while (j < m && T[i + j] == P[j]) {
++j;
}
if (j == m) {
return i;
}
}
return -1;
}

You can try using std::string::rfind which does exactly what you want:
Finds the last substring equal to the given character sequence.
Then you can have something like this:
#include <string>
#include <iostream>
std::string::size_type reverse_find(std::string const& str, std::string const& substr) {
return str.rfind(substr);
}
int main() {
auto first = reverse_find("asdhuifdsahdfasasd", "asd");
if (std::string::npos != first) {
std::cout << first << std::endl; // 15
}
auto second = reverse_find("asdhuifdsahdfasasd", "z");
if (std::string::npos != second) {
std::cout << second << std::endl; // won't be outputted
}
return 0;
}
Demo
Above reverse_find function returns 15 because indices start at 0.

int findchr(LPCWSTR str, LPCWSTR substr)
{
int n = lstrlenW(str);
int m = lstrlenW(substr);
for (int i = n; i >= m - n; --i) {
int j = 0;
while (j < m && str[i + j] == substr[j]) {
++j;
}
if (j == m) {
return i;
}
}
return -1;
}

Related

Why does the code below causes Segmentation Fault (SIGSEGV)?

PROBLEM STATEMENT
You are given a strictly increasing sequence of integers A1,A2,…,AN. Your task is to compress this sequence.
The compressed form of this sequence is a sequence of ranges separated by commas (characters ','). A range is either an integer or a pair of integers separated by three dots (the string "..."). When each range a...b in the compressed form is decompressed into the subsequence (a,a+1,…,b), we should obtain the (comma-separated) sequence A again.
For each maximal contiguous subsequence (a,a+1,…,b) of A such that b≥a+2, the compressed form of A must contain the range a...b; if b≤a+1, such a sequence should not be compressed into a range. A contiguous subsequence is maximal if it cannot be extended by at least one element of A next to it. It can be proved that the compressed form of any sequence is unique (i.e. well-defined).
Input
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
Output
For each test case, print a single line containing one string ― the compressed form of the given sequence.
Constraints
1≤T≤100
1≤N≤100
1 ≤ Ai ≤ 1000 for each valid i
A1 < A2 < …... <AN
Subtasks
Subtask #1 (100 points): Original constraints
Example Input
3
12
1 2 3 5 6 8 9 10 11 12 15 17
4
4 5 7 8
1
4
Example Output
1...3,5,6,8...12,15,17
4,5,7,8
4
MY Code:
#include <bits/stdc++.h>
using namespace std;
bool b[1005];
int a[1005];
int main()
{
int test, i, j, size, count;
cin >> test;
while (test--)
{
for (i = 0; i < 1005; i++)
b[i] = false;
cin >> size;
for (i = 0; i < size; i++)
{
cin >> a[i];
b[a[i]] = true;
}
for (i = 0; i < 1005; i++)
{
if (b[i] == true)
{
cout << i;
j = i;
count = 0;
while (b[j] == true)
{
count++;
j++;
}
if (count > 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "..." << i - 1 << ",";
else
cout << "..." << i - 1;
}
if (count == 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "," << i - 1 << ",";
else
cout << "," << i - 1;
}
if (count == 1 && ((j - 1) != a[size - 1]))
cout << ",";
}
}
}
return 0;
}
}
MY Question:
Above code runs perfectly on my device giving desired output. But when I am submitting this solution to
Online Judge , it says segmentation fault. It's sure that fundamentally I am accessing the memory incorrectly. Could you please show me where it is?
b is defined a bool[1005]
In this part
for(i=0 ; i<4000 ; i++)
b[i] = false;
You are writing false value 4000 times, exceeding the array size.
Overwriting past the array is allowed on the compiler but will have undefined behaviour in runtime.
In short: it can or can not cause a segfault.
Here is another approach given that the input data is in a file input.txt:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
class Reader {
public:
Reader(const std::string& filename) :
filename_(std::move(filename)), is_(filename_)
{
is_.exceptions( std::ifstream::failbit | std::ifstream::badbit );
}
int get_N() {
int N;
is_ >> N;
return N;
}
std::vector<int> get_ints(int N) {
std::vector<int> v;
v.reserve(N);
for (int i = 0; i < N; i++ ) {
int value;
is_ >> value;
v.push_back(value);
}
return v;
}
int get_num_cases() {
int num_cases;
is_ >> num_cases;
return num_cases;
}
private:
std::string filename_;
std::ifstream is_;
};
bool start_range_cur( std::vector<int> &v, int j, int N )
{
if ( j>= (N - 2) ) return false;
return ((v[j+1] - v[j]) == 1) && ((v[j+2] - v[j+1]) == 1);
}
bool in_range_cur( std::vector<int> &v, int j )
{
return (v[j+1] - v[j]) == 1;
}
void print_range( int min, int max, bool print_comma)
{
std::cout << min << ".." << max;
if (print_comma) std::cout << ",";
}
void print_single(int val, bool print_comma)
{
std::cout << val;
if (print_comma) {
std::cout << ",";
}
}
int main() {
Reader is {"input.txt"};
int num_cases = is.get_num_cases();
for (int i = 0; i < num_cases; i++) {
int N = is.get_N();
std::vector<int> v = is.get_ints(N);
bool in_range = false;
int range_start;
for( int j = 0; j< N; j++ ) {
if (in_range) {
if (j == (N - 1)) {
print_range(range_start, v[j], false);
}
else if (in_range_cur(v, j)) {
continue;
}
else {
print_range(range_start, v[j], true);
in_range = false;
}
}
else {
if (j == (N - 1)) {
print_single(v[j], false);
}
else if (start_range_cur(v, j, N)) {
in_range = true;
range_start = v[j];
}
else {
print_single(v[j], true);
}
}
}
std::cout << '\n';
}
return 0;
}

Find duplicate consecutive numbers in a randomly generated array

I want to find duplicate numbers in a row (2 in a row, 3 in a row, ...) in a randomly generated array. I can't make it further than this:
#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <ctime>
#include <array>
#include <algorithm>
using namespace std;
int main()
{
srand(time(NULL));
const int velikostPolja = 100;
int a[velikostPolja];
int y = 0;
int x = 0;
for (int i = 0; i < velikostPolja; i++)
{
a[i] = rand() % 10;
cout << a[i];
}
cout << endl;
for (int i = 0; i < velikostPolja; i++)
{
if (a[i] == a[i + 1])
x++;
}
cout << endl;
cout << "Two times repated in row: " << x << endl;
system("pause");
return 0;
}
You could do it like this:
int count[velikostPolja] = { 0 };
int c = 0;
for (int i = 1; i < velikostPolja; i++)
{
if (a[i] == a[i - 1])
{
++c;
}
else
{
++count[c];
c = 0;
}
}
for (int i = 1; i < velikostPolja; i++)
{
if (count[i])
{
cout << i + 1 << " times repeated in row: " << count[i] << endl;
}
}
This does not account for any repeats at the end of a, though. I leave that as an exercise for you to do yourself.
You might use:
template <typename IT>
std::size_t count_repetition(IT begin, IT end, std::size_t count)
{
std::size_t res = 0;
auto it = begin;
while (it != end) {
it = std::adjacent_find(it, end);
if (it == end){
return res;
}
const auto it2 = std::find_if(it, end, [it](const auto& e) { return e != *it; });
const auto dist = std::distance(it, it2);
if (count <= dist) {
// how to count 2-repetition for {a, a, a, a}
#if 0
++res; // Count only as 1
#else
res += dist + 1 - count; // count as 3
#endif
}
it = it2;
}
return res;
}
Demo

How to define the begin and the end value in C++?

I have an array like this:
600
250
600
600
600
I want to define the begin and the end indexes of this array where the value is greather than 500.
I made a variable which value is 2, because there are two section in my array where the values are greather than 500 (1-1 and 3-5).
So how could I output this:
1 1 3 5
The first 1 means the begin index is 1, the second 1 means the end index is also 1.
The 3 means the next section begin index where the value is greather than 500 is 3.
And the 5 means the end index of the second section is 5.
Using std:
std::vector<std::pair<std::size_t, std::size_t>>
compute_range_greater_than(const std::vector<int>& v, int threshold)
{
std::vector<std::pair<std::size_t, std::size_t>> res;
for (auto it = v.begin(); it != v.end(); /*Empty*/)
{
auto beg = std::find_if(it, v.end(), [=](int i) { return !(i < threshold); });
if (beg == v.end()) {
return res;
}
it = std::find_if(beg, v.end(), [=](int i) { return i < threshold; });
// using 1-index
res.push_back({1 + std::distance(v.begin(), beg), std::distance(v.begin(), it)});
}
return res;
}
Live Demo
Try this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
v.push_back(10);
v.push_back(200);
v.push_back(170);
v.push_back(160);
v.push_back(20);
v.push_back(300);
v.push_back(12);
v.push_back(230);
std::vector<int> indexes;
int limit = 150;
bool started = false;
for (int i = 0; i < v.size(); i++)
{
int value = v[i];
if (value > limit && !started)
{
started = true;
indexes.push_back(i);
}
else if (value < limit && started)
{
started = false;
indexes.push_back(i - 1);
}
}
if (started)
indexes.push_back(v.size() - 1);
for (int i = 0; i < indexes.size(); i++)
{
if (i % 2 == 0)
std::cout << indexes[i] << "-";
else
std::cout << indexes[i] << "; ";
}
return 0;
}
Here limit is 150, but you can change it. Output is
1-3; 5-5; 7-7;
Good luck :)
You really should consider improving your question by better explaining what you want to do and by providing code that you already wrote (and if you didnt you should do it). However, I am in a good mood, so here you go:
#include <vector>
#include <iostream>
struct BeginAndEndIndex{
int begin;
int end;
BeginAndEndIndex(int begin) : begin(begin),end(begin) {}
};
typdef std::vector<BeginAndEndIndex> IndexV;
typdef std::vector<int> IV;
IndexV findBeginAndEndIndex(const IV& in,int threshold){
IndexV result;
bool isBiggerThanThreshold = false;
for (int i=0;i<in.size();i++){
if (!isBiggerThanThreshold) {
if (in[i]>threshold){
result.push_back(BeginAndEndIndex(i));
isBiggerThanThreshold = true;
}
} else {
if (in[i]<threshold){
result.back().end = i-1;
isBiggerThanThreshold = false;
}
}
}
if (isBiggerThanThreshold){result.back().end = in.size()-1;}
return result;
}
int main(void) {
IV foo {600,250,600,600,600};
IndexV bar = findBeginAndEndIndex(foo,500);
for (int i=0;i<bar.size();i++){
std::cout << bar[i].begin << " " << bar[i].end << std::endl;
}
return 0;
}
I am pretty sure that there is a more elegant way to implement it by using std::algorithms.
Just in straight C and not storing the indices anywhere, the following code produces the exact output that you are asking for:
#include <stdio.h>
int main(int argc, char **argv)
{
int values[] = {600, 250, 600, 600, 600};
int threshhold = 500;
int begIndex = -1;
int endIndex = -1;
int i;
for (i = 0; i < sizeof(values)/sizeof(values[0]); i++)
{
if (values[i] > threshhold)
{
if (begIndex < 0)
{
begIndex = i;
}
endIndex = i;
}
else if (begIndex >= 0)
{
printf("%d %d ", begIndex + 1, endIndex + 1);
begIndex = endIndex = -1;
}
}
if (begIndex >= 0)
printf("%d %d", begIndex + 1, endIndex + 1);
printf("\n");
return 0;
}
Keep in mind the arrays in C/C++ start at zero, not one. Changing the above code to store the begIndex and endIndex pairs should be a trivial operation.

Reverse n characters in the string (there is no spaces in string) without using built-in functions in c++

I have a string like str="ABCDEFGHIJK";
need o/p like this str="CBAFEDIHGJK"
am getting "CBA" correctly after that its not printing anything.
can anyone check the following code and let me know where is the problem?
int main()
{
string str="ABCDEFGHIJK";
char str1[10],rev[10];
int n=str.length(),count=0,c=3,k=0,j=0;
for(int i=0;i<n;i++)
{
str1[i]=str[i];
count++;
cout<<str1[i]<<" and "<<count<<"and "<<c<<endl;
if(count==c)
{
cout<<"Entered into if loop"<<count<<"and"<<c<<"and "<<k<<endl;
cout<<c<<" and "<<k<<endl;
while(j<c)
{
rev[j]=str1[c-k-1];
cout<<rev[j]<<" and "<<str1[c-k-1]<<endl;
j++;
k++;
}
count=0;
}
/*else
{
if(count < c && str[i]=='\0')
{
for(int k=0;k<count;k++)
{
rev[k]=str1[count-1];
count--;
count=0;
}
}
}*/
}
cout<<"The string is: "<<rev<<endl;
return 0;
}
Please help me on this.
No need to use a c++ string object for this use-case; just use a normal char *.
Also, always make sure you store enough room for the string null-terminator character ('\0'). This is required as c string functions assume your string is terminated in this way.
Following will reverse string in ansi C89
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse(char *in, char *rev)
{
int i, n;
n = strlen(in);
for(i = n-1; i>=0; i--)
{
rev[n-i-1] = in[i];
}
/* add the null-terminator */
rev[n] = '\0';
}
int main()
{
char *str = "ABCDEFGHIJK";
char str1[12], temp;
char triplet[4];
char rev_triplet[4];
int index;
triplet[3] = '\0';
rev_triplet[3] = '\0';
str1[0] = '\0';
for(index = 0; index < strlen(str); index += 3)
{
memcpy(triplet, str + index, 3 * sizeof(char));
reverse(triplet, rev_triplet);
strcat(str1, rev_triplet);
}
printf("Initial string is: %s\n", str);
printf("Reverse string is: %s\n", str1);
return 0;
}
Outputs
$ ./test
Initial string is: ABCDEFGHIJK
Reverse string is: CBAFEDIHGKJ
If you intend to use C++ (and not C) for this:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_triples(std::string s)
{
const unsigned int N = 3;
for (int i = 0, j = N - 1; i < s.length() - (s.length() % N); i += N, j += N)
{
std::swap(s[i], s[j]);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s);
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
Whatever value of N you need can be modified (and even supplied as a function parameter if you want). You only need to swap the outer characters (so all the elements below N / 2 will be swapped with the elements above N / 2). For N == 3, it is just a single swap. If you want to do it more generically:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_substrings(std::string s, unsigned int substring_size)
{
for (int i = 0, j = substring_size - 1; i < s.length() - (s.length() % substring_size); i += substring_size, j += substring_size)
{
std::reverse(s.begin() + i, s.begin() + j + 1);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s, 4); // passing 3 gets you the same results as before
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
First, let us examine how std::reverse might be implemented. It uses iterators.
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
We can extend the logic to use indices instead of iterators, where i and j represent iterators (positions) and s[i] and s[j] represent the data pointed to by the iterators.
void reverse(std::string& s)
{
int i = 0;
int j = s.size();
while ((i != j) && (i != (--j)))
{
std::swap(s[i], s[j]);
++i;
}
}
Now you want to reverse "chunks" rather than the entire string.
void reverse(int n, std::string& s)
{
int beg = 0;
int end = beg + n;
int size = s.size();
// We're going to modify s in place
// So store a copy
std::string copy = s;
s = "";
// Add + 1 to avoid the loop cutting off short
// Or do i <= size / n;
for (int i = 0; i < size / n + 1; i++)
{
std::string chunk(copy.begin() + beg, copy.begin() + end);
// If there's no n sized chunks left
// don't reverse
if (end < size)
reverse(chunk);
s += chunk;
beg += n;
// Don't go past the size of the string
end += (end + n > size ? size - end : n);
}
}
int main()
{
std::string s("ABCDEFGHIJK");
std::string target("CBAFEDIHGJK");
reverse(3, s);
std::cout << s << "|" << target <<"|\n";
std::cout << s.size() << " " << target.size() << "\n"; // 11 11
std::cout << std::boolalpha << (s == target); // true
return 0;
}

how to check whether 2 strings are rotations to each other ?

Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html