Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to find the number of substrings in a given string. Currently, My code doesn't take account of over lapping strings.
For example
substr = "cde"
str = "cdcde"
My code:
public static int ssCount(String str, String substr) {
int count = 0;
int strlen = str.length();
int substrlen = substr.length();
int numsubstr = 0;
int substrpointer = 0;
for (int i = 0; i < strlen; i++) {
if (str.charAt(i) == substr.charAt(substrpointer)) {
substrpointer++;
count++;
}
else {
count = 0;
substrpointer = 0;
}
if (count == substrlen) {
numsubstr++;
count = 0;
}
}
return numsubstr;
}
My attempt:
public static int ssCount(String str, String substr) {
int count = 0;
int strlen = str.length();
int substrlen = substr.length();
int numsubstr = 0;
int substrpointer = 0;
int firstchar = 0;
for (int i = 0; i < strlen; i++) {
if (str.charAt(i) == substr.charAt(substrpointer)) {
substrpointer++;
count++;
if (str.charAt(i) == substr.charAt(0)) {
firstchar = i;
}
}
else {
count = 0;
substrpointer = 0;
i = firstchar;
}
if (count == substrlen) {
numsubstr++;
count = 0;
}
}
return numsubstr;
}
I tried to add a 2nd pointer that will point to the next occurrence of the first character of the substring in order to continue the comparisons from that spot. However I am having trouble because I can run into some infinite loops.
This finds all overlapping sub-strings in a larger string. The non-regex way followed by the regex way. An interesting problem.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
<P>{#code java OverlappingSubstringsXmpl}</P>
**/
public class OverlappingSubstringsXmpl {
public static final void main(String[] igno_red) {
String sToFind = "cdc";
String sToSearch = "cdcdcdedcdc";
System.out.println("Non regex way:");
int iMinIdx = 0;
while(iMinIdx <= (sToSearch.length() - sToFind.length())) {
int iIdxFound = sToSearch.indexOf(sToFind, iMinIdx);
if(iIdxFound == -1) {
break;
}
System.out.println(sToFind + " found at index " + iIdxFound);
iMinIdx = iIdxFound + 1;
}
System.out.println("Regex way:");
Matcher m = Pattern.compile(sToFind, Pattern.LITERAL).matcher(sToSearch);
boolean bFound = m.find();
while (bFound) {
System.out.println(sToFind + " found at index " + m.start());
bFound = m.find(m.start() + 1);
}
}
}
Output:
[C:\java_code\]java OverlappingSubstringsXmpl
Non regex way:
cdc found at index 0
cdc found at index 2
cdc found at index 8
Regex way:
cdc found at index 0
cdc found at index 2
cdc found at index 8
Not sure what your question is, probably how to fix your code, but my recommendation is to look into standard approaches to solving this problem, such as the KMP algorithm. It efficiently takes into account overlaps too.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
for (int i = 0; i < str1.length(); i++)
{
String c = str1.substring(i, i + 1);
for (int j = 0; j < str2.length(); j++)
{
String d = str1.substring(j, j + 1);
if (d != c)
{
System.out.println("no");
}
else
{
System.out.println("yes");
}
}
}
I know this is not even correct but I have no idea how to start.
Do you mean as you would do in the classical introductory programming exercise?
E.g. something like this?
String a = "Hello, world!";
String b = "world";
boolean contained;
contained = false;
for (int i = 0; i < a.length() - b.length() + 1 && !contained; i++) {
contained = true;
for (int j = 0; j < b.length() && contained; j++)
if (a.charAt(i + j) != b.charAt(j))
contained = false;
}
System.out.println(contained ? "b is a substring of a" : "b is not a substring of a");
How can I write a java program to check if a string is a substring of
another string without using indexOf(), contains(), etc?
There are many ways (also based on which functions/methods you use) e.g. the following solution uses String#length and String#equalsIgnoreCase in addition to String#substring (the method which you have already used in your code). The logic checks if the subject substring is equal to (ignoring case) the substring of the same length starting from an index in str.
public class Main {
public static void main(String[] args) {
// Test
System.out.println(isSubstring("World", "Hello World!"));
System.out.println(isSubstring("foo", "Hello World!"));
}
static boolean isSubstring(String substring, String str) {
if (substring == null || str == null) {
return false;
}
int len = substring.length();
for (int i = 0; i <= str.length() - len; i++) {
if (substring.equalsIgnoreCase(str.substring(i, i + len))) {
return true;
}
}
return false;
}
}
Output:
true
false
This question already has answers here:
Find the Number of Occurrences of a Substring in a String
(27 answers)
Closed 7 years ago.
Given a string, return true if the string "bat" and "ball" appear the same number of times.
MyApproach
I followed the above approach.I have taken the string "bat" and "ball".I searched in the string whether the pattern "bat" exist or not.I checked each character of the original string and compared with the characters of the bat.Similarly I searched for the pattern ball.It will return true
When both bat and ball appear same number of times.
Below is my Code with the Output.
public boolean equal(String str)
{
String str1="bat";
String str2="ball";
int l=str.length();
int l1=str1.length();
int l2=str2.length();
if((l<l1) || (l<l2))
{
return false;
}
else
{
int m=0;
int n=0;
int countbat=0;
int countball=0;
int p=0;
int j=0;
str=str.toLowerCase();
str1=str1.toLowerCase();
str2=str2.toLowerCase();
while(j<l)
{
char c=str.charAt(j);
char c1=str1.charAt(p);
if(c==c1){
p++;
if(p==l1){
countbat++;
p=0;
}
}
else{
p=0;
}
j++;
}
while(m<l)
{
char c=str.charAt(m);
char c2=str1.charAt(n);
if(c==c2){
n++;
if(n==l2){
countball++;
n=0;
}
}
else
{
n=0;
}
m++;
}
if(countbat==countball)
return true;
else
return false;
}
}
Parameters Actual Output Expected Output
'bat+ball=cricket' null true
I am not able to get the correct output.Can anyone tell me
why?
Change char "c2=str1.charAt(n);" to "char c2=str2.charAt(n);" (second while loop)
Your approach is not clear until you explain it briefly. Try this. With this your looping will be very less if you have a big string to search for ball and bat.
String name = "ball bat ball bat bat ball bat bat";
int batCount = 0;
int ballCount = 0;
int index = 0;
int startIndex = 0;
while(index != -1){
index = name.indexOf("bat", startIndex);
startIndex = index + 1;
if(index != -1){
batCount++;
}
}
index = 0;
startIndex = 0;
while(index != -1){
index = name.indexOf("ball", startIndex);
startIndex = index + 1;
if(index != -1){
ballCount++;
}
}
System.out.println(batCount); //Outputs 5
System.out.println(ballCount); //Outputs 3
Extract a method to count the occurences of one String in another. Something like,
private static int countWord(String str, String word) {
int count = 0;
for (int i = 0; i < str.length() - word.length() + 1; i++) {
if (str.substring(i, i + word.length()).equals(word)) {
count++;
}
}
return count;
}
Then you can implement your equal method like
public static boolean equal(String str) {
return countWord(str, "ball") == countWord(str, "bat");
}
Debugging the following problem (a recursive solution) and confused what is the logical meaning of the for loop. If anyone have any insights, appreciated for sharing.
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.
For example:
Given "aacecaaa", return "aaacecaaa".
Given "abcd", return "dcbabcd".
int j = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == s.charAt(j)) { j += 1; }
}
if (j == s.length()) { return s; }
String suffix = s.substring(j);
return new StringBuffer(suffix).reverse().toString() + shortestPalindrome(s.substring(0, j)) + suffix;
KMP based solution,
public class Solution {
public String shortestPalindrome(String s) {
String p = new StringBuffer(s).reverse().toString();
char pp[] = p.toCharArray();
char ss[] = s.toCharArray();
int m = ss.length;
if (m == 0) return "";
// trying to find the greatest overlap of pp[] and ss[]
// using the buildLPS() method of KMP
int lps[] = buildLPS(ss);
int i=0;// points to pp[]
int len = 0; //points to ss[]
while(i<m) {
if (pp[i] == ss[len]) {
i++;
len++;
if (i == m)
break;
} else {
if (len == 0) {
i++;
} else {
len = lps[len-1];
}
}
}
// after the loop, len is the overlap of the suffix of pp and prefix of ss
return new String(pp) + s.substring(len, m);
}
int [] buildLPS(char ss[]) {
int m = ss.length;
int lps[] = new int[m];
int len = 0;
int i = 1;
lps[0] = 0;
while(i < m) {
if (ss[i] == ss[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len == 0) {
i++;
} else {
len = lps[len-1];
}
}
}
return lps;
}
}
thanks in advance,
Lin
My original comment was incorrect - as you've pointed out, in addition to using j'to check if s is a complete Palindrome, j is also used to find (intelligently guess?) the index around which to wrap + reverse the trailing characters from the longest palindrome which might exist at the beginning of the string. My understanding of the algorithm is as follows:
e.g. aacecaaa gives j = 7, resulting in
`aacecaaa` is `aacecaa` (palindrome) + `a` (suffix)
so the shortest palindrome appending to the start is:
`a` (suffix) + `aacecaa` + `a` (suffix)
Where the suffix consists of more than one character it must be reversed:
`aacecaaab` is `aacecaa` (palindrome) + `ab` (suffix)
So the solution in this case would be:
`ba` + `aacecaa` + `ab` (suffix)
In the worst case scenario j = 1 (since a will match when i=0 and j=0), e.g. abcd has no palindrome sequence in it, so the best which can be done is to wrap around the first character
dcb + a + bcd
To be honest, I'm not 100% confident that the algorithm you are debugging will work correctly in all cases but can't seem to find an a failed test case. The algorithm is certainly not intuitive.
Edit
I believe the shortest Palindrome can be derived deterministically, without the need for recursion at all - it seems that in the algorithm you are debugging, the recursion masks a side effect in the value of j. In my opinion, here's a way to determine j in a more intuitive manner:
private static String shortestPalindrome(String s) {
int j = s.length();
while (!isPalindrome(s.substring(0, j))) {
j--;
}
String suffix = s.substring(j);
// Similar to OP's original code, excluding the recursion.
return new StringBuilder(suffix).reverse()
.append(s.substring(0, j))
.append(suffix)
.toString();
}
I've pasted some test cases with an implementation of isPalindrome on Ideone here
public String shortestPalindrome(String s) {
String returnString ="";
int h = s.length()-1;
if(checkPalindrome(s))
{
return s;
}
while(h>=0)
{
returnString =returnString + s.charAt(h);
if(checkPalindrome(returnString+s))
{
return returnString+s;
}
h--;
}
return returnString+s;
}
public boolean checkPalindrome(String s)
{
int midpoint = s.length()/2;
// If the string length is odd, we do not need to check the central character
// as it is common to both
return (new StringBuilder(s.substring(0, midpoint)).reverse().toString()
.equals(s.substring(s.length() - midpoint)));
}
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 8 years ago.
Improve this question
import java.util.StringTokenizer;
public class PigLatins {
String str1;
int vowelIndex;
String[] vowels = {"a","e","i","o","u","A","E","I","O","U"};
String counter = "";
public String pigLatin(String str) {
String[] result = str.split("\\s");
for (int x=0; x<result.length; x++) {
for(int i = 0;i<vowels[i].length();i++) {
if(!result[x].contains(vowels[i])) {
str1 = result[x]+"ay";
}
else if(result[x].startsWith(vowels[i])) {
str1 = result[x]+"ay";
}
for(int j = 0;j<result[x].length();j++)
if(Character.toString(result[x].charAt(j)) == vowels[i]) {
vowelIndex = j;
break;
}
if(vowelIndex > 0 && !result[x].startsWith(vowels[i]) && result[x].contains(vowels[i])) {
str1 = result[x].substring(1,vowelIndex) + result[x].substring(0,1) + "ay";
}
}
counter+=str1;
}
return counter;
}
}
At this part result[x].substring(1,vowelIndex) in the if statement, it seems to return null, why is it wrong and how could I fix it? (I removed the driver class as stackoverflow told me to I had too much code)
You should change :
for(int i = 0;i<vowels[i].length();i++)
to
for(int i = 0;i<vowels.length;i++)
Since you want to iterate over all the vowels in the array.
vowels[i].length() will always give you 1, since it's the length of the i'th String in the vowels array.
Beside that, it would make more sense to change the vowels array from String[] to char[].
the problem here is that the vowelIndex is 0 while you start in index 1 for the substring.
i don't quite understand what you are trying to achive but you need to check in you if statement the value of vowelIndex:
if(vowelIndex > 0 && !result[x].startsWith(vowels[i]) && result[x].contains(vowels[i]))
the whole function should be
public String pigLatin(String str) {
String[] result = str.split("\\s");
for (int x=0; x<result.length; x++) {
for(int i = 0;i<vowels[i].length();i++) {
if(!result[x].contains(vowels[i])) {
str1 = result[x]+"ay";
}
else if(result[x].startsWith(vowels[i])) {
str1 = result[x]+"ay";
}
for(int j = 0;j<result[x].length();j++)
if(Character.toString(result[x].charAt(j)) == vowels[i]) {
vowelIndex = j;
break;
}
if(vowelIndex > 0 && !result[x].startsWith(vowels[i]) && result[x].contains(vowels[i])) {
str1 = result[x].substring(1,vowelIndex) + result[x].substring(0,1) + "ay";
}
}
counter+=str1;
}
return counter;
}
also you should not use an array of strings of you need an array of charecters, or if i understand correctly you should use a set of charecters
I am learning regular expression.Suppose, If I have two String like abcd & bcdd. To make them equal Strings I have to remove a from first and d from last string. is this possible to count the matched number like bcd=> (3).
Currently, I am doing this
Pattern p= Pattern.compile("["+abcd+"]{2}");
Matcher m= p.matcher("abcd bcdd");
My current solution doesn't provide me the correct result. So, my question
1) Is this possible ?
2) If possible, then how can I achieve that ?
Hope, you will help to increase my regular expression knowledge.
Not sure why you would use regex at all, if all you need is the number of "bcd"s. I've put both a non-regex and regex version here for comparison.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
<P>{#code java BcdRegexXmpl}</P>
**/
public class BcdRegexXmpl {
public static final void main(String[] igno_red) {
String sSentence = "abcd bcdd";
int iBcds = 0;
int iIdx = 0;
while(true) {
int iBcdIdx = sSentence.indexOf("bcd", iIdx);
if(iBcdIdx == -1) {
break;
}
iIdx = iBcdIdx + "bcd".length();
iBcds++;
}
System.out.println("Number of 'bcd's (no regex): " + iBcds);
//Alternatively
iBcds = 0;
//Same regex as #la-comadreja, with word-boundaries
//(for multiple "bcd"-s in a single word, remove the "\\b"-s)
Matcher m = Pattern.compile("\\b\\w*bcd\\w*\\b").matcher(sSentence);
while(m.find()) {
System.out.println("Found at index " + m.start());
iBcds++;
}
System.out.println("Number of 'bcd's (with regex): " + iBcds);
}
}
Output:
[R:\jeffy\programming\sandbox\xbnjava]java BcdRegexXmpl
Number of 'bcd's (no regex): 2
Found at index 0
Found at index 5
Number of 'bcd's (with regex): 2
Your pattern should be:
(a?)(bcd)(d?)
Another possibility is to write it as
\w*bcd\w*
If you want to count the number of "bcd"s in the string:
int bcds = 0;
for (int i = 0; i < str.length() - 2; i++) {
if (str.charAt(i) == 'b' && str.charAt(i+1) == 'c' && str.charAt(i+2) == 'd')
bcds++;
}
A maximally generalizable, concise and readable (and reasonably efficient) non-Regex answer:
int countMatches(String s, String searchStr) {
//Here, s is "abcd bcdd" and searchStr is "bcd"
int matches = 0;
for (int i = 0; i < s.length() - searchStr.length() + 1; i++) {
for (int j = 0; j < searchStr.length(); j++) {
if (s.charAt(i + j) != searchStr.charAt(j)) break;
if (j == searchStr.length() - 1) matches++;
}
}
return matches;
}