This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the cost / complexity of a String.indexof() function call
What is the complexity of java indexof(String str) method. I mean there are String matching algorithms like KMP which runs in linear time. I am implementing a system that needs to search for large substring in a really large string,so can I use java indexof(String str) method or I should to implement KMP.
The complexity of Java's implementation of indexOf is O(m*n) where n and m are the length of the search string and pattern respectively.
What you can do to improve complexity is to use e.g., the Boyer-More algorithm to intelligently skip comparing logical parts of the string which cannot match the pattern.
java indexOf function complexity is O(n*m) where n is length of the text and m is a length of pattern
here is indexOf original code
/**
* Returns the index within this string of the first occurrence of the
* specified substring. The integer returned is the smallest value
* <i>k</i> such that:
* <blockquote><pre>
* this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* is <code>true</code>.
*
* #param str any string.
* #return if the string argument occurs as a substring within this
* object, then the index of the first character of the first
* such substring is returned; if it does not occur as a
* substring, <code>-1</code> is returned.
*/
public int indexOf(String str) {
return indexOf(str, 0);
}
/**
* Returns the index within this string of the first occurrence of the
* specified substring, starting at the specified index. The integer
* returned is the smallest value <tt>k</tt> for which:
* <blockquote><pre>
* k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then -1 is returned.
*
* #param str the substring for which to search.
* #param fromIndex the index from which to start the search.
* #return the index within this string of the first occurrence of the
* specified substring, starting at the specified index.
*/
public int indexOf(String str, int fromIndex) {
return indexOf(value, offset, count,
str.value, str.offset, str.count, fromIndex);
}
/**
* Code shared by String and StringBuffer to do searches. The
* source is the character array being searched, and the target
* is the string being searched for.
*
* #param source the characters being searched.
* #param sourceOffset offset of the source string.
* #param sourceCount count of the source string.
* #param target the characters being searched for.
* #param targetOffset offset of the target string.
* #param targetCount count of the target string.
* #param fromIndex the index to begin searching from.
*/
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j] ==
target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
you can simply implements the KMP algorithm without using of indexOf Like this
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Scanner;
public class Main{
int failure[];
int i,j;
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
String pat="",str="";
public Main(){
try{
int patLength=Integer.parseInt(in.readLine());
pat=in.readLine();
str=in.readLine();
fillFailure(pat,patLength);
match(str,pat,str.length(),patLength);
out.println();
failure=null;}catch(Exception e){}
out.flush();
}
public void fillFailure(String pat,int patLen){
failure=new int[patLen];
failure[0]=-1;
for(i=1;i<patLen;i++){
j=failure[i-1];
while(j>=0&&pat.charAt(j+1)!=pat.charAt(i))
j=failure[j];
if(pat.charAt(j+1)==pat.charAt(i))
failure[i]=j+1;
else
failure[i]=-1;
}
}
public void match(String str,String pat,int strLen,int patLen){
i=0;
j=0;
while(i<strLen){
if(str.charAt(i)==pat.charAt(j)){
i++;
j++;
if(j==patLen){
out.println(i-j);
j=failure[j-1]+1;
}
} else if (j==0){
i++;
}else{
j=failure[j-1]+1;
}
}
}
public static void main(String[] args) {
new Main();
}
}
Related
I am newbie here!!
I am unable to understand how "s.indexOf(s.charAt(i), s.indexOf(s.charAt(i)) + 1) == -1 "
checking for unique letter in the string. Below is the code,
String s = "leetcode";
for (int i = 0; i < s.length(); i++) {
if (s.indexOf(s.charAt(i), s.indexOf(s.charAt(i)) + 1) == -1) {
return i;
}
}
return -1;
Thank you for your help!
I am trying to find the unique character in the given string. I came across this code. I am trying to understand how it work!
For a rather verbose function like this, the best thing to do is break it down to the smallest possible computation (effectively).
Please refer to the following code snippet:
public class App {
private static int unique(String s) {
/** The String (non-primitive) is an array of chars (primitive).
* So, it'll be iterated with a loop. S.length () is the length of the char array.
*/
for (int i = 0; i < s.length(); i++) {
/** This will return the char element of the index i -> public char charAt(int index) */
char chatAtI = s.charAt(i);
/** Follow the println logs to see what's happening, or use a debugger on an IDE. */
System.out.println("chatAtI -> " + chatAtI);
/** Returns the index within this string of the first occurrence of the specified character
* or -1 if the character does not occur.
*/
int charIndex = s.indexOf(chatAtI) + 1;
System.out.println("charIndex -> " + charIndex);
/** The indexOf() method returns the position of the first occurrence of a specified character(s) in a string.
* It's an overloaded method.
* In the if condition, you're also using the variant which [1] returns the index of the first char occurrence
* and [2] start the search at the specified index or -1 if the character does not exist.
* The moment a unique occurrence is found, it'll return the index;
* meaning - "if the current char doesn't repeat in the char array, return its index and exit the method."
* Keep in mind the +1 above is what does the trick, as if that character doesn't repeat indexOf() returns -1.
*/
if (s.indexOf(chatAtI, charIndex) == -1) {
return i;
}
}
return -1;
}
public static void main(String[] args) {
/** l is the first unique occurrence. Therefore, its index, 0, is returned. */
System.out.println(unique("leetcode"));
}
}
Articles for further reading:
https://www.digitalocean.com/community/tutorials/java-char-to-string-to-char-array
https://www.freecodecamp.org/news/charat-in-java-how-to-use-the-java-charat-method-2/
https://www.geeksforgeeks.org/java-string-indexof/
I hope this made sense. If not, let me know, as I can edit the answer and give more context.
Hi I'm new to this and I don't know how to continue analyzing this algorithm that I have done myself, the conclusion I have right now is:
T(n) ϵ Ω(2n+1)
ϵ O(2n+max)
S(n) ϵ Θ(max)
'max' -> Maximum integer value in the array.
'n' -> Is the input size which is the length of the array.
Is this analysis correct?, 'max' will make it linear? and how can I express this better?
Thanks for the help.
Code
/**
* Method findUnique2
*
* Finds the unique number inside an array of integers
* in which there are always 1 unique number and the rest
* are repeated exactly twice.
*
* NOTE:
* This implementation only works with positive integer numbers.
*
* #param v -> Array with the integer numbers.
* #return The unique number.
*/
public static int findUnique2(int[] v)
{
int max = getMax(v); // Get the maximum number
int[] repetitions = new int[max+1];
boolean found = false;
// +1 to every position
for(int i=0; i<v.length; i++)
repetitions[v[i]]++;
/*
* Finally traversing the array an the position with
* a 1 is the unique number the rest can be either 0
* of not used or 2 which is a repeated number.
*/
int i = -1;
while(!found)
{
i++;
if(repetitions[i] == 1)
found = true;
}
return i;
}
/**
* Method getMax
*
* Traverse an array of integers and returns the maximum
* number stored inside it.
*
* #param v An array of integers
* #return the maximum number among the given array.
*/
public static int getMax(int[] v)
{
int max = v[0];
for(int i=1; i<v.length; i++)
if (max < v[i])
max = v[i];
return max;
}
This question already has answers here:
Getting permutations of an int[] removing duplicates sets
(5 answers)
Closed 7 years ago.
I want to generate all distinct permutations of array of integers. The array may contain duplicates. but i want to generate all distinct permutations. I have tried next permutation and recursive methods which tend to be very slow. Please suggest.
There are n! different permutations of n elements. Generating a single permutation is cost n (strictly) so the minimum cost of any permutation generation algorithm would be O(n*n!)
Steinhaus–Johnson–Trotter algorithm is one of those algorithms. There are improvements like Shimon Even's and other algorithms like Heap's but none get them under O(n*n!)
Googling "permutation algorithm" gets several different algorithms you can implement, although most use recursion and that means another stack step. Steinhaus–Johnson–Trotter is defined as iterative, so shouldn't get that problem.
Here's a Java implementation
import java.util.Arrays;
import java.util.Iterator;
/**
* this implementation is based in Steinhaus–Johnson–Trotter algorithm and
* Shimon Even's improvement;
*
* #see https
* ://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm
*
*/
public class Permutations implements Iterator<int[]> {
/**
* direction[i] = -1 if the element i has to move to the left, +1 to the
* right, 0 if it does not need to move
*/
private int[] direction;
/**
* inversePermutation[i] is the position of element i in permutation; It's
* called inverse permutation because if p2 is the inverse permutation of
* p1, then p1 is the inverse permutation of p2
*/
private int[] inversePermutation;
/**
* current permutation
*/
private int[] permutation;
/**
* #param numElements
* >= 1
*/
public Permutations(int numElements) {
// initial permutation
permutation = new int[numElements];
for (int i = 0; i < numElements; i++) {
permutation[i] = i;
}
// the support elements
inversePermutation = Arrays.copyOf(permutation, numElements);
direction = new int[numElements];
Arrays.fill(direction, -1);
direction[0] = 0;
}
/**
* Swaps the elements in array at positions i1 and i2
*
* #param array
* #param i1
* #param i2
*/
private static void swap(int[] array, int i1, int i2) {
int temp = array[i1];
array[i1] = array[i2];
array[i2] = temp;
}
/**
* prepares permutation to be the next one to return
*/
private void buildNextPermutation() {
// find the largest element with a nonzero direction, and swaps it in
// the indicated direction
int index = -1;
for (int i = 0; i < direction.length; i++) {
if (direction[permutation[i]] != 0
&& (index < 0 || permutation[index] < permutation[i])) {
index = i;
}
}
if (index < 0) {
// there are no more permutations
permutation = null;
} else {
// element we're moving
int chosenElement = permutation[index];
// direction we're moving
int dir = direction[chosenElement];
// index2 is the new position of chosenElement
int index2 = index + dir;
// we'll swap positions elements permutation[index] and
// permutation[index2] in permutation, to keep inversePermutation we
// have to swap inversePermutation's elements at index
// permutation[index] and permutation[index2]
swap(inversePermutation, permutation[index], permutation[index2]);
swap(permutation, index, index2);
// update directions
if (index2 == 0 || index2 == permutation.length - 1
|| permutation[index2 + dir] > permutation[index2]) {
// direction of chosen element
direction[chosenElement] = 0;
}
// all elements greater that chosenElement set its direction to +1
// if they're before index-1 or -1 if they're after
for (int i = chosenElement + 1; i < direction.length; i++) {
if (inversePermutation[i] > index2) {
direction[i] = -1;
} else {
direction[i] = 1;
}
}
}
}
#Override
public boolean hasNext() {
return permutation != null;
}
#Override
public int[] next() {
int[] result = Arrays.copyOf(permutation, permutation.length);
buildNextPermutation();
return result;
}
}
Hi I am working with a voice command project. So I want to receive user's voice at first then I want to check the matches and then I want to do something according to the command. For this, I found a way to match the strings using org.apache.commons.lang3.StringUtils but I find so many trouble with this. For ex:- I face problem when I go to import the apache's external library to my android studio.
So my question is that:- is there any other way to compare the user's voice data and my specific command without using Apache's StringUtils method? Please help if you can
Take the source right from the library (Obviously follow the requirements of the Apache license)
https://commons.apache.org/proper/commons-lang/apidocs/src-html/org/apache/commons/lang3/StringUtils.html
Line 6865
/**
* <p>Find the Levenshtein distance between two Strings.</p>
*
* <p>This is the number of changes needed to change one String into
* another, where each change is a single character modification (deletion,
* insertion or substitution).</p>
*
* <p>The previous implementation of the Levenshtein distance algorithm
* was from http://www.merriampark.com/ld.htm</p>
*
* <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
* which can occur when my Java implementation is used with very large strings.<br>
* This implementation of the Levenshtein distance algorithm
* is from http://www.merriampark.com/ldjava.htm</p>
*
* <pre>
* StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException
* StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException
* StringUtils.getLevenshteinDistance("","") = 0
* StringUtils.getLevenshteinDistance("","a") = 1
* StringUtils.getLevenshteinDistance("aaapppp", "") = 7
* StringUtils.getLevenshteinDistance("frog", "fog") = 1
* StringUtils.getLevenshteinDistance("fly", "ant") = 3
* StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
* StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
* StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
* StringUtils.getLevenshteinDistance("hello", "hallo") = 1
* </pre>
*
* #param s the first String, must not be null
* #param t the second String, must not be null
* #return result distance
* #throws IllegalArgumentException if either String input {#code null}
* #since 3.0 Changed signature from getLevenshteinDistance(String, String) to
* getLevenshteinDistance(CharSequence, CharSequence)
*/
public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
if (s == null || t == null) {
throw new IllegalArgumentException("Strings must not be null");
}
/*
The difference between this impl. and the previous is that, rather
than creating and retaining a matrix of size s.length() + 1 by t.length() + 1,
we maintain two single-dimensional arrays of length s.length() + 1. The first, d,
is the 'current working' distance array that maintains the newest distance cost
counts as we iterate through the characters of String s. Each time we increment
the index of String t we are comparing, d is copied to p, the second int[]. Doing so
allows us to retain the previous cost counts as required by the algorithm (taking
the minimum of the cost count to the left, up one, and diagonally up and to the left
of the current cost count being calculated). (Note that the arrays aren't really
copied anymore, just switched...this is clearly much better than cloning an array
or doing a System.arraycopy() each time through the outer loop.)
Effectively, the difference between the two implementations is this one does not
cause an out of memory condition when calculating the LD over two very large strings.
*/
int n = s.length(); // length of s
int m = t.length(); // length of t
if (n == 0) {
return m;
} else if (m == 0) {
return n;
}
if (n > m) {
// swap the input strings to consume less memory
final CharSequence tmp = s;
s = t;
t = tmp;
n = m;
m = t.length();
}
int p[] = new int[n + 1]; //'previous' cost array, horizontally
int d[] = new int[n + 1]; // cost array, horizontally
int _d[]; //placeholder to assist in swapping p and d
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
char t_j; // jth character of t
int cost; // cost
for (i = 0; i <= n; i++) {
p[i] = i;
}
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; i++) {
cost = s.charAt(i - 1) == t_j ? 0 : 1;
// minimum of cell to the left+1, to the top+1, diagonally left and up +cost
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
// copy current distance counts to 'previous row' distance counts
_d = p;
p = d;
d = _d;
}
// our last action in the above loop was to switch d and p, so p now
// actually has the most recent cost counts
return p[n];
}
There are many string functions you can use to compare strings, for example
if (result.equals("hello")) {
doSomething();
}
compares two strings
result.startsWith("search for") {
doSomething()
}
checks the beginning of the result
result.matches("yes|sure") {
doSomething()
}
checks result with regular expression.
You can find all that in a Java textbook. See for example
https://docs.oracle.com/javase/tutorial/java/data/comparestrings.html
If you want to use Levenshtein distance you can insert the following function in your code:
public int LevenshteinDistance (String s0, String s1) {
int len0 = s0.length() + 1;
int len1 = s1.length() + 1;
// the array of distances
int[] cost = new int[len0];
int[] newcost = new int[len0];
// initial cost of skipping prefix in String s0
for (int i = 0; i < len0; i++) cost[i] = i;
// dynamically computing the array of distances
// transformation cost for each letter in s1
for (int j = 1; j < len1; j++) {
// initial cost of skipping prefix in String s1
newcost[0] = j;
// transformation cost for each letter in s0
for(int i = 1; i < len0; i++) {
// matching current letters in both strings
int match = (s0.charAt(i - 1) == s1.charAt(j - 1)) ? 0 : 1;
// computing cost for each transformation
int cost_replace = cost[i - 1] + match;
int cost_insert = cost[i] + 1;
int cost_delete = newcost[i - 1] + 1;
// keep minimum cost
newcost[i] = Math.min(Math.min(cost_insert, cost_delete), cost_replace);
}
// swap cost/newcost arrays
int[] swap = cost; cost = newcost; newcost = swap;
}
// the distance is the cost for transforming all letters in both strings
return cost[len0 - 1];
}
I have tested that my partitioning algorithm works well, but when it comes time in the implementation to make use of it, I get an array that is not sorted. Since this is for a class, there's a certain I need to write the class itself so that I can return the answer as string. My problem is most likely in the qkSort() method. Here's the code:
private static int splitterElement;
public static void main (String[] args){
System.out.println(myMethod());
}
public static String myMethod() {
String result = "";
int[] testArray = null;
testArray = populateArray(testArray, 7, 10);
result += "Before sort: \n" + printArray(testArray);
testArray = qkSort(testArray,1,testArray.length);
result += "After sort: \n" + printArray(testArray);
return result;
}
//Method to continually call the partition() method
public static int[] qkSort(int[] x, int left, int right){
if (right - left >= 1) {
//after running this method, the global variable splitterElement is assigned.
x = partition(x,left,right);
qkSort(x,left,splitterElement-1);
qkSort(x,splitterElement + 1,right);
}
//base case. if right-left = 0, then the array length is 1,
//and that is already sorted
return x;
}
/**
* Populates an integer array with random integers. Should be used only with
* non-itialized integer arrays.
*
* #param x an uninitialized array of integers and will be returned once it is populated.
* #param sizeOfArray The size that array x will be initialized to.
* #param rangeOfValues The range of values that that each element can be. This value should
* not surpass the maximum value for integers, but no error-checking is performed.
* #return
*/
public static int[] populateArray (int[] x, int sizeOfArray, int rangeOfValues){
x = new int[sizeOfArray];
for (int i = 0; i < sizeOfArray; i++){
x[i] = (int)(Math.random() * rangeOfValues); //place a random number from 0 to rangeOfValues into array.
}
return x;
}
/**
*
* #param x An integer array. It is assumed that x is initialized when the method is called.
* #param left
* #param right The length of the array can be used for the right int.
* #see #populateArray(int[], int, int)
* #return
*/
public static int[] partition (int[] x, int left, int right){
//element of the splitter
int l = (int) (Math.random() * x.length);
splitterElement = l;
x = swap (x,left,l);
//value of the splitter
int t = x[left];
int i = left;
for (int j = left + 1; j < right; j++){
if (x[j] < t){
i++;
x = swap (x,i,j);
}
}
x = swap(x,left,i);
return x;
}
/**
* Places the value at index1 in index2, and places the value at index2 in index1.
*
* #param array The array that will be worked on.
* #param index1 The first place we will switch values.
* #param index2 The second place we will switch values.
* #return
*/
public static int[] swap (int[] array, int index1, int index2){
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
return array;
}
/**
* A simple print method that prints an array.
* #param array Input.
*/
public static String printArray (int[] array){
String result = "";
for (int i = 0; i < array.length; i++){
result += array[i] + " ";
}
result += "\n";
return result;
}
}
Output:
Before sort:
8 9 7 3 4 2 6
After sort:
8 6 3 9 7 2 4
Thanks for any ideas on what my problem is!
I see several issues in your code:
1) the methods don't need to return the array, you could find a better use for the return value
2) using a global variable splitterElement doesn't work because its value can change during the first recursive call to qkSort. Method partition could return its value instead of returning the array, which is useless.
3) the first line of the partition method:
int l = (int) (Math.random() * x.length);
should be:
int l = left + (int) (Math.random() * (right - left));
because youre partitionning the range between left and right, not the whole array.