Solved

# java substring challenge

Posted on 2014-10-22
478 Views
hi,

I was going through below challenge
http://codingbat.com/prob/p178318

I have not understood the problem clearly

Given a string, return the count of the number of times that a substring length 2 appears in the string and also as the last 2 chars of the string, so "hixxxhi" yields 1 (we won't count the end substring).

last2("hixxhi") → 1
last2("xaxxaxaxx") → 1
last2("axxxaaxx") → 2

Are they saying substring could be xx and aa as well or only xx(excluding last one)r. Please advise
0
Question by:gudii9
• 24
• 14
• 11
• +5

LVL 84

Assisted Solution

ozo earned 100 total points
ID: 40397191
In the examples "xaxxaxaxx" and "axxxaaxx" the substring could only be xx

last2("hixxhi") → 1
We count this one:  "hixxhi"
last2("xaxxaxaxx") → 1
We count this one: "xaxxaxaxx"
last2("axxxaaxx") → 2
We count these two: "axxxaaxx"  "axxxaaxx"
0

LVL 7

Author Comment

ID: 40397458
0

LVL 84

Expert Comment

ID: 40397466
We don't count it because it doesn't appear "as the last 2 chars of the string"
0

LVL 7

Author Comment

ID: 40397505
if my Sting is like " yqaawaataa" then substring count is 2 and substring is "aa" right
0

LVL 84

Expert Comment

ID: 40397539
That would be my understanding.
0

LVL 27

Expert Comment

ID: 40398097
A tip would be to start by finding the last 2 characters in the string.

Then decide how often those 2 characters appear elsewhere in the string.

Doug
0

LVL 16

Expert Comment

ID: 40398772
So any String less than 4 chars long will return zero. (Just an observation here) ;)
0

LVL 10

Expert Comment

ID: 40398778
imagine the string "aaaa", what is the return value?
0

LVL 16

Expert Comment

ID: 40398785
@oleber -

is your comment directed at the OP or me?
0

LVL 16

Expert Comment

ID: 40399328
As oleber may be referring to - a String such as "xxxx" (which is one of their test strings) is a dubious one in my opinion, because you can't have a return value of 2 for that, if the last pair of "xx"s  is supposed to fall outside the ambit. The challenge doesn't mention overlapping !

Another test shows the ambiguity I am talking about :

last2("1717171") → 2

because in the "xxxx" text, the third char is being borrowed to make a second match. But in the "17" scenario, the third "7" isn't being borrowed - so I have no idea what they have in mind. But I could, of course, be wrong.
0

LVL 84

Expert Comment

ID: 40399341
overlapping is implied by
last2("axxxaaxx") → 2
and
last2("xxxx") → 2
seems to imply that some String less than 4 chars long may return non-zero
0

LVL 16

Expert Comment

ID: 40399354
ozo - yes, but look at the "17" scenario.
0

LVL 16

Expert Comment

ID: 40399402
And, as has been covered  before by many of us, (mccarl made the point first), using for-next (as the answer suggests) for this question is not as efficient as skipping the counter to the last-found incidence of the substring.

String searching in serious contexts would take far longer than necessary using a for-next; whereas a selective increment would be far more productive.
0

LVL 84

Expert Comment

ID: 40399446
Do you mean the example ending with "71"?
last2("1717171") → 2
Overlap does not apply here, so we count these two: "1717171"  "1717171"
0

LVL 32

Assisted Solution

awking00 earned 100 total points
ID: 40399458
public int last2(String str) {
String last2 = str.substring(str.length() -2,str.length());
String notLast2 = str.substring(0,str.length() -2);
int counter = 0;
for (int i = 0; i < notLast2.length() - 1; i++) {
String pair = notLast2.substring(i, i + 2);
if (pair.equals(last2)) {
counter++;
}
}
System.out.println(str + "  " + counter);
return counter;
}
0

LVL 16

Expert Comment

ID: 40399485
Do you mean the example ending with "71"?

Ah - well spotted! Looks like I suffered from some dyslexia here! My bad.
0

LVL 16

Expert Comment

ID: 40399492
@ awking -

that code will not pass all tests.
0

LVL 16

Assisted Solution

krakatoa earned 200 total points
ID: 40399497
You'd have to do this :

``````public int last2(String str) {

int count=0;

if(str.length()<4){return 0;}

String end = str.substring(str.length()-2);
String front = str.substring(0,str.length()-1);
int a=0;

while(front.indexOf(end,a)>-1){

a=(front.indexOf(end,front.indexOf(end,a)))+1;
count++;

}
return count;
}
``````
0

LVL 7

Author Comment

ID: 40399867
``````public class Test20 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i=last2("axexxwexxwxx");
System.out.println("i is--->"+i);
}

public static int last2(String str) {
int len=str.length();
int count=0;
int initialCount=0;
if(len>4){
if((str.substring(len-2,len-1)).equals((str.substring(len-2,len-1))))
{
for(int i=0;i<len;i++){
if(str.contains("xx")){
initialCount = initialCount+1;

}
count=initialCount-1;

}
}
else{
count=0;
}
}

return count;

}
}
``````

I wrote as above based on thoughts came to my mind i got wrong output
i is--->11

0

LVL 16

Expert Comment

ID: 40399872
Haven't checked it all yet, but len>4 should be len>=4 for one thing.

This will always be true :
if((str.substring(len-2,len-1)).equals((str.substring(len-2,len-1))))

. . .do you really want that? I'm surprised it even compiles.
0

LVL 32

Expert Comment

ID: 40399927
Think of what is happening. The length of the string is 12. The substring of the string starting at index 10 (length - 2) and ending at index 11 (length - 1) is always going to equal the substring of the string starting at index 10 (length - 2) and ending at index 11 (length - 1) so the program always goes into the for loop, which says loop from 0 to less than 12 (meaning 11) or 12 loops (i.e. 0,1,2,3,4,5,6,7,8,9,10,11) and then, if the string contains "xx" anywhere (which it always does) add 1 to the initialCount so at the end of the looping, the initalCount would be 12 and initialCount minus 1 would make the count be 11 and you never reach the else, so 11 is returned.
0

LVL 16

Expert Comment

ID: 40399949
if the string contains "xx" anywhere (which it always does)

No it doesn't always contain "xx". Look at the examples it has to run.
0

LVL 16

Expert Comment

ID: 40400004
Your code gudii would need to shape more to

``````public int last2(String str) {
int len=str.length();
int count=0;
//int initialCount=0;
if(len>=4){
//if((str.substring(len-2,len-1)).equals((str.substring(len-2,len-1))))
//{
for(int i=0;i<len-2;i++){
if(str.substring(i,i+2).equals(str.substring(str.length()-2,str.length()))){
//initialCount = initialCount+1;
count++;

}
//count=initialCount-1;

}
//}
//else{
//count=0;
//}
}

return count;
}
``````
0

LVL 7

Author Comment

ID: 40400064
``````public class Test20 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i=last2("axexxwexxwxx");
System.out.println("i is--->"+i);
}

public static int last2(String str) {
int len=str.length();
int count=0;
int initialCount=0;
if(len>=4){
if((str.substring(len-2,len-1)).equals((str.substring(len-1,len))))
{
for(int i=0;i<=len-2;i++){
if((str.substring(i,i+2)).equals((str.substring(len-2,len)))){
initialCount = initialCount+1;

}
count=initialCount-1;

}
}
else{
count=0;
}
}

return count;

}
}
``````

I modified as above and got right output
i is--->2

Below statement
for(int i=0;i<=len-2;i++){

if i give like

for(int i=0;i<=len-1;i++){

I am getting index outpfbound. I wonder why. I usually remember giving i<=len-1(since lenght is always 1 more than index since index starts with 0).
What is the difference between my code and your code.
0

LVL 7

Author Comment

ID: 40400083
``````public int last2(String str) {
int len=str.length();
int count=0;
//int initialCount=0;
if(len>=4){
//if((str.substring(len-2,len-1)).equals((str.substring(len-2,len-1))))
//{
for(int i=0;i<len-2;i++){
if(str.substring(i,i+2).equals(str.substring(str.length()-2,str.length()))){
//initialCount = initialCount+1;
count++;

}
//count=initialCount-1;

}
//}
//else{
//count=0;
//}
}

return count;
}
``````

In the challenge mentioned as below
so "hixxxhi" yields 1 (we won't count the end substring).

0

LVL 16

Expert Comment

ID: 40400096

I am going to be busy for a while. I would say you ought to look at the differences between the code that works and that which doesn't, and go over the logic flows in your own mind.
0

LVL 27

Expert Comment

ID: 40400128

This is handled by the loop stopping at "len-2" rather than "len":

for(int i=0;i<len-2;i++){
...
}

So the part where we're counting the number of matches in the string, stops 2 characters before the end of the string.

So it (correctly) doesn't count the last 2 characters as a "match".

Doug
0

LVL 7

Author Comment

ID: 40400186

public class Test20 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i=last2("axexxwexxwxx");
System.out.println("i is--->"+i);
}

public static int last2(String str) {
int len=str.length();
int count=0;
int initialCount=0;
if(len>=4){
if((str.substring(len-2,len-1)).equals((str.substring(len-1,len))))
{
for(int i=0;i<=len-2;i++){
if((str.substring(i,i+2)).equals((str.substring(len-2,len)))){
initialCount = initialCount+1;

}
count=initialCount-1;

}
}
else{
count=0;
}
}

return count;

}
}

how my code also working fine where i have to subtract by one

count=initialCount-1;
0

LVL 32

Expert Comment

ID: 40400269
krakatoa,
>>that code will not pass all tests. <<
What test does it not pass?
>>No it doesn't always contain "xx". Look at the examples it has to run.<<
I was referring to his specific example where he has set the value of str to "axexxwexxwxx" in his code and, as strings are not immutable, it will always contain "xx"

gudii9,
Your test of if (str.substring(len-2,len-1).equals(str.substring(len-1,len)) is testing to see if the next to last character matched the last character, so it will not take care of the instance where the last two characters are different (as with the case of "hixxhi").
>>how my code also working fine where i have to subtract by one<<
Because your searching the entire string except the last two characters, but you only need to search the portion of the string without the two end characters up to the point of its next to last character (or the whole string except the last 3) since you're looking for a two-character combination.
0

LVL 32

Expert Comment

ID: 40400275
I meant to say "as Strings are immutable" above.
0

LVL 7

Author Comment

ID: 40400282
``````Because your searching the entire string except the last two characters, but you only need to search the portion of the string without the two end characters
``````

I did not clearly get it. Above two sounding same to me. please advise
0

LVL 32

Expert Comment

ID: 40400322
The string you are testing is "axexxwexxwxx" and your program is testing the portion in bold of the string (i.e. "axexxwexxwxx) but it only needs to test the portion up to the next to last character of that portion (i.e. "axexxwexxwxx") since you're looking for a matching string of two.
0

LVL 7

Author Comment

ID: 40400327
``````public int last2(String str) {
String last2 = str.substring(str.length() -2,str.length());
String notLast2 = str.substring(0,str.length() -2);
int counter = 0;
for (int i = 0; i < notLast2.length() - 1; i++) {
String pair = notLast2.substring(i, i + 2);
if (pair.equals(last2)) {
counter++;
}
}
// System.out.println(str + "  " + counter);
return counter;
}
``````

when i tried as above failing two test cases as below

Expected      Run
last2("hixxhi") → 1      1      OK
last2("xaxxaxaxx") → 1      1      OK
last2("axxxaaxx") → 2      2      OK
last2("xxaxxaxxaxx") → 3      3      OK
last2("xaxaxaxx") → 0      0      OK
last2("xxxx") → 2      1      X
last2("13121312") → 1      1      OK
last2("11212") → 1      1      OK
last2("13121311") → 0      0      OK
last2("1717171") → 2      2      OK
last2("hi") → 0      0      OK
last2("h") → 0      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: -1 (line number:2)      X
last2("") → 0      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: -2 (line number:2)

0

LVL 7

Author Comment

ID: 40400339
This is handled by the loop stopping at "len-2" rather than "len":

for(int i=0;i<len-2;i++){
...
}

So the part where we're counting the number of matches in the string, stops 2 characters before the end of the string.

So it (correctly) doesn't count the last 2 characters as a "match".
when i write as below getting index out of bound. please advise

``````public int last2(String str) {
int len=str.length();
int count=0;
//int initialCount=0;
if(len>=4){
//if((str.substring(len-2,len-1)).equals((str.substring(len-2,len-1))))
//{
for(int i=0;i<len;i++){
if(str.substring(i,i+2).equals(str.substring(str.length()-2,str.length()))){
//initialCount = initialCount+1;
count++;

}
//count=initialCount-1;

}
//}
//else{
//count=0;
//}
}

return count;
}
``````

Expected      Run
last2("hixxhi") → 1      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 7 (line number:9)      X
last2("xaxxaxaxx") → 1      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 10 (line number:9)      X
last2("axxxaaxx") → 2      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 9 (line number:9)      X
last2("xxaxxaxxaxx") → 3      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 12 (line number:9)      X
last2("xaxaxaxx") → 0      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 9 (line number:9)      X
last2("xxxx") → 2      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 5 (line number:9)      X
last2("13121312") → 1      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 9 (line number:9)      X
last2("11212") → 1      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 6 (line number:9)      X
last2("13121311") → 0      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 9 (line number:9)      X
last2("1717171") → 2      Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 8 (line number:9)      X
last2("hi") → 0      0      OK
last2("h") → 0      0      OK
last2("") → 0      0
0

LVL 32

Expert Comment

ID: 40400352
As for "xxx", I'm getting a result of 0, which I believe to be correct. As for "h" or any single character string, you will get an index out of bounds exception. The solution to that is to wrap the code in an if (str.length() > 1) with a default value of 0.
0

LVL 16

Expert Comment

ID: 40400444
@awking00

You should know that your code does not pass the tests at the codingbat site, on which the OP is working. The link is at the top of his question, and if you try your code there as you posted it, you will see that it doesn't work in all cases.
0

LVL 27

Expert Comment

ID: 40400488
You've got 2 solutions on the go at once now - so this is getting a bit complicated :)

But working with the first of these - you get an exception for the cases where the string is really short - because the code to lookup the last 2 characters:
String last2 = str.substring(str.length() -2,str.length());

only works if the length is >= 2.

Try this slightly modified version (I also removed the notlast2 string as it's not needed at all):

``````public int last2(String str) {
if (str.length() < 2)
return 0 ;

String last2 = str.substring(str.length() -2,str.length());
int counter = 0;
for (int i = 0; i < str.length()-2; i++) {
String pair = str.substring(i, i + 2);
if (pair.equals(last2)) {
counter++;
}
}
return counter;
}
``````
0

LVL 86

Assisted Solution

CEHJ earned 100 total points
ID: 40401731
Here's another - minimising substringing (which is relatively expensive)

``````   public int last2(String str) {
int result = 0;
int pos = 0;
int len = str.length();
if (len > 2) {
String lastTwo = str.substring(len - 2);
while ((pos = str.indexOf(lastTwo, pos)) > -1) {
result++;
pos++;
}
result--;
}
return result;
}
``````
0

LVL 32

Expert Comment

ID: 40401934
CEHJ,
I like it, although I think the "if (len > 2)" condition needs to be modified to "if (len > 3)" as "xxx" would produce a result of 1 instead of 0.
0

LVL 16

Expert Comment

ID: 40401949
It *should* produce a result of 1, not 0. That's what I pointed out to you once before.
0

LVL 32

Expert Comment

ID: 40401976
I guess there's a misinterpretation of "we won't count the end substring". I'm taking it to mean that the last two characters can not be any part of the test and you're seeming to say that as long as the two characters exist at any index before the last two characters, the test is met.
0

LVL 84

Expert Comment

ID: 40402008
I agree that the problem description leaves room for interpretation,
and the tests leave interpretations for "xxx" undetermined, but
last2("xxxx") → 2
would seem to support the view that "xx" appears at 3 places in "xxxx", of which one at the end does not count.
0

LVL 7

Author Comment

ID: 40402352
``````public class Test20 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i = last2("axexxwexxwxxqxx");
System.out.println("i is--->" + i);
}

public static int last2(String str) {
int len = str.length();
int count = 0;

if (len <= 2)
return count;

for (int i = 0; i < len - 2; i++) {
if (str.substring(i, i + 2).equals(
str.substring(str.length() - 2, str.length()))) {
System.out.println("str.substring(i,i+2)-->"
+ str.substring(i, i + 2));

count++;

}

}

return count;
}
}
``````

i modified as above and all test cases passing and got out put as
str.substring(i,i+2)-->xx
str.substring(i,i+2)-->xx
str.substring(i,i+2)-->xx
i is--->3

axexxwexxwxxq(len-3,i=12)x(len-2,i=13)x(len-1,i=14)
For above string
length 15
so once i=12

based on this
if(str.substring(i,i+2).equals(str.substring(str.length()-2,str.length()))){
code looks for str.substring(12,14) which is qx right not xx with last two terms(xx)
0

LVL 16

Expert Comment

ID: 40402389
code looks for str.substring(12,14) which is qx right

. . . well, it looks for xq actually.

@awking and ozo :

not interpretation if you want to pass the tests. But as I said originally, the last two chars should be ignored for partial inclusion in overlapping finds for the search string in the remainder of the string. I think this question was a mess on their part.
0

LVL 86

Expert Comment

ID: 40402480
as "xxx" would produce a result of 1 instead of 0.

It should do afaics. Anyway it passes all the tests and that's good enough for me ;)
0

LVL 84

Expert Comment

ID: 40402510
The tests do not resolve the question of whether last2("xxx") should be 0 or 1, but they do resolve the question of whether last2("xxxx") should be 1 or 2.

But regardless of the former question, for which there is insufficient information to answer definitively, and for which we can all find justification for our own opinions,
gudii9 is now able to pass all the tests, so the question seems moot.
0

LVL 7

Author Comment

ID: 40402546
code looks for str.substring(12,14) which is qx right

. . . well, it looks for xq actually.
axexxwexxw x   x   q    x    x
0123456789 10 11 12 13 14

As per above indexing positions and based on the link below i thought it is 'qx' not 'xq'. please advise

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int,%20int)

public String substring(int beginIndex,
int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.
Examples:

"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"

Parameters:
beginIndex - the beginning index, inclusive.
endIndex - the ending index, exclusive.
0

LVL 84

Expert Comment

ID: 40402563
"axexxwexxwxxqxx".substring(12,14) is qx, as you can see
System.out.println( "axexxwexxwxxqxx".substring(12,14) );
0

LVL 7

Author Comment

ID: 40402595
public class Test20 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i = last2("axexxwexxwxxqxx");
System.out.println("i is--->" + i);
}

public static int last2(String str) {
int len = str.length();
int count = 0;
System.out.println( "axexxwexxwxxqxx".substring(12,14) );
if (len <= 2)
return count;

for (int i = 0; i < len - 2; i++) {
if (str.substring(i, i + 2).equals(
str.substring(str.length() - 2, str.length()))) {
System.out.println("str.substring(i,i+2)-->"
+ str.substring(i, i + 2));

count++;

}

}

return count;
}
}

i also got qx

as below

qx
str.substring(i,i+2)-->xx
str.substring(i,i+2)-->xx
str.substring(i,i+2)-->xx
i is--->3
0

LVL 16

Expert Comment

ID: 40402652
This question has become overcomplicated and the OP doesn't seem satisfied with any of the answers, and continues to go off on a tangent and try something else, so having said all I can say, I'm now out of this one.

And I do believe the question was a mess from the start - a string of 2 chars is just that, and simply because there was a case of overlapping in a previous question, doesn't mean that that pertains this time. "xxx" should be zero. Ciao.
0

LVL 16

Expert Comment

ID: 40403116
As there is no limit on interpretations, this one will do all the tests except the two which are based on overlap.

``````public int last2(String str) {
int num=0;
int totlen=0;

if(str.length()<4){return 0;}
String[] sA = str.split(str.substring(str.length()-2));

for(int i=0; i<sA.length;i++){

totlen = totlen + sA[i].length();
}
num = ((str.length()-totlen)-2)/2;

return num;
}
``````
0

LVL 27

Expert Comment

ID: 40403288
The last code you posted (gudii9) seems to be fine.

Is this problem solved for you now?  I'm not sure I understand what else you're asking.

``````	public int last2(String str) {
int len = str.length();
int count = 0;

if (len <= 2)
return count;

for (int i = 0; i < len - 2; i++) {
if (str.substring(i, i + 2).equals(
str.substring(str.length() - 2, str.length()))) {

count++;

}

}

return count;
}
``````
0

LVL 16

Accepted Solution

krakatoa earned 200 total points
ID: 40403313
I don't think we've had this one yet either . . .

``````public int last2(String str) {

int len = str.length();
int count = 0;
int i = 0;

if (len <= 2){return count;}

while (i < len - 2) {

if (str.substring(i, i+2).equals(str.substring(len - 2))) {
i = str.indexOf(str.substring(len-2),i)+1;
count++;
}
else{i=i+1;}
}

return count;
}
``````
0

LVL 7

Author Comment

ID: 40405332
``````	public int last2(String str) {
int len = str.length();
int count = 0;

if (len <= 2)
return count;

for (int i = 0; i < len - 2; i++) {
if (str.substring(i, i + 2).equals(
str.substring(str.length() - 2, str.length()))) {

count++;

}

}

return count;
}
``````

I like all the solutions above. In the above solution below line was earlier confusing but now it is clear
if (str.substring(i, i + 2).equals(
str.substring(str.length() - 2, str.length())))
we are checking for last iternation as below for string axexxwexxwxxqxx

if (str.substring(12, 14).equals(
str.substring(13, 15)))

since qx.equals("xx")that one is not counted.
And our for loop ending there so last 'xx' also not counting. Now it all make sense.

One last question with last post

while (i < len - 2) {

if (str.substring(i, i+2).equals(str.substring(len - 2))) {
i = str.indexOf(str.substring(len-2),i)+1;
count++;
}
else{i=i+1;}
}

Above code is not clear with below line
i = str.indexOf(str.substring(len-2),i)+1;

0

LVL 16

Expert Comment

ID: 40405463
It's just incrementing the index position again from where to start searching, either to the position where it found the last "xx" (or whatever it's looking for), or, if it didn't find "xx", then it increments the start search position by 1, and searches the rest of the reference string again for it. It keeps doing this, until it cant find "xx" any more in the part of the string that exists after you subtract the last two characters from the original string.

I'm pleased you like all our suggestions. And talking about favourites - not that I am biased of course - my personal sweetheart is the one I posted which uses String.split(). This makes Java do the decisive part, and leaves you to play with a bit of simple maths. ;)
0

LVL 84

Expert Comment

ID: 40405478
0

LVL 16

Expert Comment

ID: 40405488
Who me?
0

LVL 84

Expert Comment

ID: 40405524
The one who asked "What it means."
0

LVL 27

Expert Comment

ID: 40405542
Above code is not clear with below line
i = str.indexOf(str.substring(len-2),i)+1;

That's a pretty complicated line.  You might find it easier to see what it's doing if it was broken into 2 parts like this:

``````while (i < len - 2) {
String end = str.substring(len-2) ; // Last 2 characters in the string

if (str.substring(i, i+2).equals(end)) {
i = str.indexOf(end,i)+1;
count++;
}
else{i=i+1;}
}
``````

Now the line becomes:
i = str.indexOf(end,i)+1;

This uses a slightly more advanced version of "indexOf" where you start searching for the substring (end in this case) from position 'i', rather than from the start of the string.

So in English this is basically:
- Find the position in the string 'str' where end appears, starting the search from position 'i'

Does that make sense?
0

LVL 84

Expert Comment

ID: 40405552
Doing String end = str.substring(len-2) outside the loop can also be useful for not having to re-calculate str.substring(len-2) multiple times
0

LVL 27

Expert Comment

ID: 40405651
Yeah - I just wasn't sure if he was going to put it before the guard, get an error and get confused.  Hence why it's in the loop :)
0

LVL 16

Expert Comment

ID: 40406069
Call me slow to see the penny drop, but I *have* to say this :

this infamous "overlapping" issue is a nonsense in terms of this particular question. Why, well because you can have an overlapping "xx" (inside "xxx" for example), there's no such thing as an overlapping "hi" (nor any of the other heterogeneous tail-end substrings in the challenge). What would an overlapping "hi" look like - "hh", "ii"  - "ih" perhaps ? Lol.
0

LVL 7

Author Comment

ID: 40406449
i = str.indexOf(end,i)+1;

instead of above we have to  say as below if no overlapping is allowed right? please advise

i = str.indexOf(end,i)+1;

I tried like
``````public class Test20 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i = last2("axexxwexxwxxxqxx");
System.out.println("i is--->" + i);
}

public static int last2(String str) {

int len = str.length();
int count = 0;
int i = 0;

if (len <= 2) {
return count;
}

//		while (i < len - 2) {
//
//			if (str.substring(i, i + 2).equals(str.substring(len - 2))) {
//				i = str.indexOf(str.substring(len - 2), i) + 1;
//				count++;
//			} else {
//				i = i + 1;
//			}
String end = str.substring(len-2) ; // Last 2 characters in the string
while (i < len - 2) {

if (str.substring(i, i+2).equals(end)) {
i = str.indexOf(end,i)+2;
count++;
}
else{i=i+1;}
}

return count;
}
}
``````

i got output of xx count without overlap
i is--->3

i = str.indexOf(end,i)+4;

even i say as above i still get same output
i is--->3

what is the significance of else loop with incrementing i value by 1(can we increment by 2 or 3 instead?

else{i=i+1;}
0

LVL 16

Expert Comment

ID: 40406771
public int last2(String str) {  /*beginning of method. Suck in a String for analysis. Ensure an int is returned.*/

int len = str.length(); /*capture the length of the String you've been given, in case you need it.*/
int count = 0; /* declare an int variable as a counter, and prime it so it's ready to use.*/
int i = 0; /* declare and assign another int variable, to use as a loop counter. Doing it this way just makes what's going on in the while loop a tiny bit clearer, as it's decluttered from other terms, but usually, you'd handle this counter INSIDE the loop - most likely moreso in a for loop. Anyway, read on.*/

if (len <= 2){return count;} /* if the length of the String is less than 3, then forget doing anything else, and just return 0, as we have been given a String that won't satisfy any of the criteria. And the main criterion was to see how many times the last 2 characters of the String are repeated throughout the String, with the exception of taking into account the last two characters. Since a String of length 3 or less cannot possibly fulfil this criterion, we may as well save a bit of processing time, and chuck it out a priori.*/

while (i < len - 2) { /* Here we go then - we seem to have an eligible String. So all the time the variable i (which at the moment is zero) is less than the length of the String -2, then let's do this :*/

if (str.substring(i, i+2).equals(str.substring(len - 2))) {/* Oow, here's another condition - we've got to ensure that even though I might be less than the length of the string-2, we further have to ensure that the part of the string which starts at position i, and goes on for 2 more characters past i, is equal to the last 2 characters of the String. And IF IT IS, then BINGO . . . we've FOUND a match; so we may as well prepare ourselves for the eventuality that there will be ANOTHER match further up the string, so let us now increment i, so that it points further up the string, and doesn't get stuck looking at the same old boring part of the string that we anyway just looked at. So here we go - let's increment i :*/
i = str.indexOf(str.substring(len-2),i)+1; /* i can now be set to ONE PLACE* more than where we just found our searched-for substring. We were looking in str, right, at the index position (i**) of the occurrence of these last two characters in the entire string (str.substring(len-2)) SO REALLY THIS LINE OF CODE SAYS "MAKE i EQUAL TO WHERE YOU FIND THE SUBSTRING (that instruction is up to the "+1" part of the code. BUUUUUUUUT, just as you thought we were about to leave this line of code, Java's precedence evaluation engine ALLOWS US TO ADD A POST ASSIGNMENT INCREMENT to that value, and so we move i on by 1, by saying :"+1". GOTCHA!! Now we have i right where we want it - ready to give a starting index for the NEXT loop of the search, which doesn't repeat the last starting position and waste out time.*/
count++; /* and because we met the above If condition (which was that those two chars at that particular i position, going on for 2 chars, WAS the same as the end two chars of the entire String (which is our overriding criterion), we can now increment the number of times counter that we have found the string by 1 !! Yippee!*/
}
else{i=i+1;} /* BUT, if we didn't find our two chars at that position, then we have to be prepared that they might be at the NEXT POSSIBLE position, and that NEXT POSSIBLE position can only be 1 character further along the string, because we can't afford to skip over anything, as it might contain what we are looking for, so an increment of 1 is the ONLY possible step we can make. Right?*/
} /* I may not look like much, but I'm the loop folder. I think we should go back to the top of the while loop, and check that we've seen all this darn string before we shoot our mouth off and return some number that doesn't mean squat.*/

return count; /* Oow - we searched all the string, and I'm sending back the number that we found. */
} /* I end the method - and remember, when you re-read the narrative alongside these comments, increase i and count each time where appropriate, and ask the same questions all over again. But whichever way you look at it, the loop will only exit when we've looked at the entire string, after which the method ends.*/
0

LVL 27

Expert Comment

ID: 40406782
And who says the art of documentation is dead :)
0

LVL 16

Expert Comment

ID: 40406792
Lol. ;)

My art is verbatim-  yours always cleaner and clearer. ;)

BTW OP, Doug ought really to have had 100 of my points  I think! We overkilled this one, as the lawd is my witness.
0

LVL 32

Expert Comment

ID: 40406851
krakatoa,
I salute your latest response. I was in the process of generating a very lengthy response going line by line defining what each was doing when the acceptance came across, so I stopped and I'm glad I did since my editorial didn't have nearly the levity or brevity or your illustrious response. Good show!
0

LVL 16

Expert Comment

ID: 40406951

I feel like I've been "sleeping in the office" since this question began, sometimes with only the cleaner to talk to as it were - all present company excepted of course.

Now you've come back through the door, it's like we are in the neighbourhood bar for a couple of trauma-taming beers, trying to get our lives back on track. ;)

And as we leave after our last drink, swaying from side to side, someone says "Hey fellas., did you guys ever clear up that overlapping thing?". We stop - eye contact. You say - "uh, shiiiiiiiishhhh man, who cares?!!".

I whisper to myself "yeah, well it was never really anything to ever need clearing up."

Outside, Doug draws a six-shooter and says "you guys think you're gonna slide off with my points then, do-ya?"
0

Expert Comment

ID: 41821055
I wrote this program in C#  language. It works fine. Let's try this your own language. Here i am not using any builtin functions.

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter the string");
string last = "";
int size = s.Length - 2,count=0,j=0;
for (int i = 0; i < s.Length; i++)
{
if (i >= size)
{
last = last + s[i];
}
}
for (int i = 0; i < size-1; i++)
{

if (last[j] == s[i] && last[j + 1] == s[i + 1])
{
count++;
}

}
Console.WriteLine(count);
}
}
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question