The question is to count how many permutations of a string B have an equivalent pattern into a bigger string A. For example, if A="aabbccd" and B="xx", then it should print 3, since "aa", "bb", "cc" are all substrings of A which share the same pattern as B.
I have tried to pass the substrings as numbers, such as xx becomes "11" and do the same for string A, but I still can't get it to work. Any ideas? Length can be up to 10^7.
Here's the code for changing pattern:
void transform(int* dest, char* original, int len) {
int j=1;
Al[original[0]-'a']=j;
dest[0]=j;
j++;
for (int i=1;i<len;i++) {
if (Al[original[i]-'a']==0)
Al[original[i]-'a']=j++;
dest[i]=Al[original[i]-'a'];
}
}
Concept: Use Regular Expressions
You would need the following regular expression (\\w)\\1{(REPETITIONS-1)}
I don't know about C but Java provides a library to compile RegEx patterns. Here's a class that implements just what you want:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringPatternPermutation {
public static void main(String[] args) {
int REPETITIONS = 3;
String REGEX = "(\\w)\\1{" + (REPETITIONS-1) + "}";
String INPUT = "abbbbbbccddeffff";
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
int count = 0;
while(m.find()){
String match = m.group();
System.out.println(match);
count++;
}
System.out.println(count);
}
}
Here's a test of the code above: https://ideone.com/5nztaa
Here's a useful website to test any RegEx: https://regexr.com/
Without Regular Expressions
public class StringPatternPermutation {
public static void main(String[] args) {
String a = "abjjjiixsssppw";
String b = "qwwwee";
String patternA = detectPattern(a);
String patternB = detectPattern(b);
System.out.println("-String A: " + a);
System.out.println("-Pattern A: " + patternA);
System.out.println("-String B: " + b);
System.out.println("-Pattern B: " + patternB);
System.out.println("-A contains B? " + patternA.contains(patternB));
int count = 0;
int index = 0;
while((index = patternA.indexOf(patternB)) != -1){
count++;
patternA = patternA.substring(index+1, patternA.length());
}
System.out.println("-Number of occurances: " + count);
}
private static String detectPattern(String a){
StringBuilder sb = new StringBuilder();
char prev = a.charAt(0);
int count = 1;
for(int i = 1; i < a.length(); i++){
char curr = a.charAt(i);
if(curr == prev)
count++;
else {
sb.append(count + ", ");
prev = curr;
count = 1;
}
if(i == a.length() - 1){
sb.append(count);
}
}
return sb.toString();
}
}
Test it on ideOne: https://ideone.com/w422Du
Related
I been trying to implement what been discussed here in this thread Algorithm to apply permutation in constant memory space. However I am not able to may be understand the problem solution correctly or my code has some bug which I cant detect and fix. Ant kind of help is appreciated.
public class ArrayPermute{
public static void main(String[] args){
char[] arr = {'a','b','c','d'};
int[] p = {2,0,1,3};
for(int i=0; i<arr.length; i++){
int tmp = i;
while(p[tmp] >= 0){
char t = arr[p[tmp]];//d
arr[p[tmp]] = arr[tmp];
arr[tmp]=t;
int _tmp = p[tmp];
p[tmp] = -1;
tmp = _tmp;
print(arr);
print(p);
}
}
for(char i: arr){
System.out.print(i + " ");
}
}
public static void print(char[] arr){
for(char c: arr){
System.out.print(c + " " );
}
System.out.println();
}
public static void print(int[] arr){
for(int c: arr){
System.out.print(c + " " );
}
System.out.println();
}
}
Don't use the very array elements to keep the displaced values (i.e. swap between the elements of the initial array), this is how you screwed your code.
Instead, use some O(1) temp variables to keep the "displaced" value and where from that value originated.
Commented code below, with 2 test cases (note the use of Arrays.toString instead of your custom print(char[]/int[]) methods)
import java.util.Arrays;
public class InPlacePermutation {
static public void inPlacePermute(char arr[], int p[]) {
for(int i=0; i<p.length; i++) {
if(p[i]<0) continue; // already visited
char toMove=arr[i]; // value-at-hand
int currIx=i; // index from where the value-at-hand originated
while(currIx>=0 && p[currIx]!=i) { // as long as we aren't back where we started
int destIx=p[currIx];
if(destIx<0) {
// the permutation is bad, we are stepping again
// on places we stepped before. This should not happen
throw new IllegalArgumentException("bad permutation");
}
// take the value "at hand" before it get overwritten
char destVal=arr[destIx];
// place current "value at hand" in the destination
arr[destIx]=toMove;
// update bookkeeping the vals/indexes values
p[currIx]=-1; // mark where we've been
currIx=destIx; // then take a step further
toMove=destVal; // don't forget to carry the new "value at hand"
}
// now we are back where we started with a "value at hand"
arr[i]=toMove;
p[currIx]=-1; // mark the source of the moved value as visited
}
}
static public void main(String[] args) {
char[] arr = {'a','b','c','d'};
int[] p = {2,0,1,3};
System.out.print("arr:"+Arrays.toString(arr)+" + pmt:"+Arrays.toString(p) + " =>");
inPlacePermute(arr, p);
System.out.println(" "+Arrays.toString(arr));
System.out.println();
// two cycles and one in place
arr = new char[]{'a','b','c','d', 'e', 'f'};
p = new int[]{2,3,4,1,0,5};
System.out.print("arr:"+Arrays.toString(arr)+" + pmt:"+Arrays.toString(p) + " =>");
inPlacePermute(arr, p);
System.out.println(" "+Arrays.toString(arr));
}
}
Output:
arr:[a, b, c, d] + pmt:[2, 0, 1, 3] => [b, c, a, d]
arr:[a, b, c, d, e, f] + pmt:[2, 3, 4, 1, 0, 5] => [e, d, a, b, c, f]
You don't need to make a swap when your reach the beginning of the cycle. That is, it should go like:
int tmp = i;
int start = i;
while (p[tmp] >= 0 && p[tmp] != start) {
// Your code here doesn't change
}
if (p[tmp] == start) {
p[tmp] = -1;
}
If the given input is a1bc2def3 then output should be abcbcdefdefdef
Whenever the number comes then we should repeat previous substring that many number of times.
Please provide the algorithm or code to accomplish this.
Here's another approach that doesn't rely on regex.
public String splitRepeat(String str)
{
StringBuilder out = new StringBuilder();
boolean number = false;
for(int i=0,j=0,k=0; i<=str.length(); i++)
{
if(i==str.length() || Character.isDigit(str.charAt(i)) != number)
{
if(number)
{
for(int r = Integer.parseInt(str.substring(j, i)); r>0; r--)
{
out.append(str.substring(k, j));
}
}
else
{
k=j;
}
j=i;
number = !number;
}
}
return out.toString();
}
My suggestion would be:
Try using regex so you can get an array of numbers and characters,
then convert the number Parsable elements of the array into an integer,
after that loop with the index of the arrays to append n-times the characters of the array
then print the final result
Example:
public static void main(String[] args) {
String stringToProcess = "a1bc2def3";
String[] regexSplitted = stringToProcess.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
StringBuilder sb = new StringBuilder();
String appender = "";
for (int i = 0; i < regexSplitted.length; i++) {
try {
int kilo = Integer.parseInt(regexSplitted[i]);
for (int j = 0; j < kilo; j++) {
sb.append(appender).append(regexSplitted[i - 1]);
appender = "-";
}
} catch (NumberFormatException e) {
}
}
System.out.println(sb.toString());
}
this will print
a-bc-bc-def-def-def
that is pretty much what you are looking for.
I am trying to take an array of information (array of 8) and split it so that I can send it to an ArrayList.
I can run a a split if I create and make them all strings, but I am trying to reduce the coding (as there has to be a better way).
The first 4 of the array are strings, and the next 4 are int.
ArrayList<student> studentID = new ArrayList<student>();
String[] studentInfo = {"","","",""};
int [] studentInfo2 = {0,0,0,0};
for (int x = 0; x < students.length; x++)
{
if (x < 4)
{
studentInfo = students[x].split(",");
}
else
{
**studentInfo2 = students[x]();**
}
for (int counter = 0; counter < 8; counter++)
{
if (counter < 4) //First 4 in the array are strings
{
studentID.add(new student(studentInfo[counter]));
}
else //Everything after the first 4 are Integers
{
studentID.add(new student(Integer.valueOf(studentInfo[counter])));
}
}
}
I cannot figure out how to split the last 4 into an array, as I did the first 4.
EDIT:
static String[] students = "1,John,Smith,John2233#gmail.com,20,88,79,59,
2, Becky,Jones,JonesBecky123#hotmail.com,44,90,89,44,99"
This information is being piped into a class as seen below:
public class student
{
private String studentNumber;
private String firstName;
private String lastName;
private String emailAddress;
private int age;
private int []score = {0,0,0};
private int score0;
private int score1;
private int score2;
/**
* Constructor for objects of class studentObject
*/
public student(String theStudentNumber, String theFirstName, String theLastName, String theEmailAddress, int theAge, int theScore0, int theScore1, int theScore2)
{
// initializing the instance variables
studentNumber = theStudentNumber;
firstName = theFirstName;
lastName = theLastName;
emailAddress = theEmailAddress;
age = theAge;
score[0] = theScore0;
score[1] = theScore1;
score[2] = theScore2;
}
Then it will call this method
public void print(student printStudentInfo)
{
System.out.print(printStudentInfo.getStudentNumber()+"\t");
System.out.print("First Name: " + printStudentInfo.getStudentNumber()+"\t");
System.out.print("Last Name: " + printStudentInfo.getStudentNumber()+"\t");
System.out.print("Age: " + printStudentInfo.getStudentNumber()+"\t");
System.out.print("Scores : " + printStudentInfo.getStudentNumber()+"\t");
System.out.println();
}
Thanks for the help ahead of time.
1.The two copies should be done in a single for loop.
2.The output should be made in a separate loop.The output should display 5 lines for each number on each one of the arrays as follows. “ARRAY1[index]= xx ARRAY2[index] = XX ARRAY3[index] = XX” Array3 should contain the first arrays numbers but reversed (5-1).
public static void main(String[] args)
{
// Constants Section
final int FIVE = 5;
final int ONE = 1;
// Variable Declaration Section
int[] firstArray = {1,2,3,4,5};
int[] secondArray;
int[] finalArray;
int i;
// Variable Initialization Section
secondArray = new int[FIVE];
finalArray = new int[FIVE];
// Code Section
for (i = 0; i <FIVE; i++)
{
secondArray = firstArray;
finalArray = firstArray;
}
for (i = FIVE - 1; i >= 0; i--)
{
System.out.println("Array1 = " + firstArray[i] + " Array2= " + secondArray[i] + " Array3= " + finalArray [i]);
}
}
}
PLEASE HELP, IM A HIGH SCHOOL STUDENT WHO IS COMPLETELY CLUELESS ABOUT PROGRAMMING. (THE SIMPLER THE BETTER)
I think this is what you need!
public static void main(String[] args)
{
// Constants Section
final int FIVE = 5;
final int ONE = 1;
// Variable Declaration Section
int[] firstArray = {1,2,3,4,5};
int[] secondArray;
int[] finalArray;
int i;
// Variable Initialization Section
secondArray = new int[FIVE];
finalArray = new int[FIVE];
// Code Section
for (i = 0; i <FIVE; i++)
{
secondArray[i] = firstArray[i];
finalArray[i] = firstArray[FIVE-i-1];
}
//For Printing you can loose any logic. This would print in the reverse order but if you want your could change the loop
for (i = FIVE - 1; i >= 0; i--)
{
System.out.println("Array1 = " + firstArray[i] + " Array2= " + secondArray[i] + " Array3= " + finalArray [i]);
}
}
}
I think this should do it, Correct me if i misunderstood..
Here's my code.
public static String hBlanks(String a, String b){
StringBuilder blanks = new StringBuilder();
int j;
for(int x = 0; x < a.length(); x++){
blanks.append('-');
}
System.out.println(blanks);
String strBlanks = blanks.toString();
for(int i = 0; i < a.length(); i++){
j = 0;
while(j < b.length()){
boolean check = a.contains(b.charAt(j));
//I keep getting an error on the boolean check = a.contains(b.charAt(j)); line. It says: "contains(java.lang.CharSequence) in java.lang.String cannot be applied to (char)"
if(check == true){
strBlanks = blanks.replace('-', "" + a.charAt(i));
//And I get another error at the str = strBlanks.replace('-', "" + a.charAt(i)); line. That one says "cannot find symbol
symbol : method replace(char,java.lang.String)
location: class java.lang.String"
}else{
j++;
}
}
return strBlanks;
}
}
To get rid of your compilation issues,
Change strBlanks.replace('-', "" + a.charAt(i)); to
strBlanks.replace('-', a.charAt(1));
Also change a.contains(b.charAt(j)); to
a.contains("" + b.charAt(1));
How about just one line, instead of all that code:
public static String wordBlanks(String a, CharSequence b){
return a.replaceAll("[^" + b + "]", "-");
}
This works by creating a regex that matches every character not in b and using that to replace ever occurrence in a with a dash.