I have a problem for my task. I must make a program that the input is a palindrome / not a palindrome, and the output is return the substring of the string that can be a palindrome in recursive. Example :
"marah" , the output should be, ("m","a","r","a","h") , ("m","ara","h") . I dont know to implement this in recursive. Please anyone who can help me, i'm very need that code. I worked it in java. Thank you, i hope there is a help coming :D .
public static String palindrome(String s) {
String s, sub;
int i, c, length;
Scanner in = new Scanner(System.in);
System.out.println("Enter a string to print it's all substrings");
s = in.nextLine();
length = string.length();
System.out.println("Substrings of \"" + string + "\" are :-");
for (c = 0; c < length; c++) {
for (i = 1; i <= length - c; i++) {
sub = string.substring(c, c + i);
System.out.println(sub);
}
}
}
public static String longestPalindrome(String s) {
if (s.isEmpty()) {
return null;
}
if (s.length() == 1) {
return s;
}
String longest = s.substring(0, 1);
for (int i = 0; i < s.length(); i++) {
// get longest palindrome with center of i
String tmp = helper(s, i, i);
if (tmp.length() > longest.length()) {
longest = tmp;
}
// get longest palindrome with center of i, i+1
tmp = helper(s, i, i + 1);
if (tmp.length() > longest.length()) {
longest = tmp;
}
}
return longest;
}
// Given a center, either one letter or two letter,
// Find longest palindrome
public static String helper(String s, int begin, int end) {
while (begin >= 0 && end <= s.length() - 1 && s.charAt(begin) == s.charAt(end)) {
begin--;
end++;
}
return s.substring(begin + 1, end);
}
if the input is "mama", the output is only "ama", the expected is, "m","a","m","a" , "mam","a" , and "m","ama" . Anybody can help?
This is called palindrom partition, you can find it here http://www.programcreek.com/2013/03/leetcode-palindrome-partitioning-java/
Related
In this program, I am trying to return a new string that is composed of new letters that were added and old letters if the didn't fit the constraints. I am stuck in terms of I don't know how to fix my code so that it prints correctly. Any help or suggestions is greatly appreciated!
Here are some examples:
str: "asdfdsdfjsdf", word: "sdf", c: "q"
should return "aqdqjq", I'm getting "asdqqq"
str: "aaaaaaaa", word: "aaa", c: "w"
should return "wwaa", as of right now my code only returns "ww"
public static String replaceWordWithLetter(String str, String word, String c)
String result = "";
int index = 0;
while (index < str.length() )
{
String x = str.substring(index, index + word.length() );
if (x.equals(word))
{
x = c;
index = index + word.length();
}
result = result + x;
index++;
}
if (str.length() > index)
{
result = result + str.substring(index, str.length() - index);
}
return result;
}
You seem to be overcomplicating this. You can simply use the replace() method:
public static String replaceWordWithLetter(String str, String word, String c) {
return str.replace(word, c);
}
Which when called as:
replaceWordWithLetter("asdfdsdfjsdf", "sdf", "q")
Produces the output:
aqdqjq
The problem with your current method is that if the substring is not equal to word, then you will append as many characters as there are in word, and then only move up one index. If you will not be replacing the sequence, then you only need to append one character to result. Also it is much more efficient to use a StringBuilder. Also as noted if the String is not divisible by word.length(), this will throw a StringIndexOutOfBoundsError. To solve this you can use the Math.min() method to ensure that the substring does not go out of bounds. Original method with fixes:
public static String replaceWordWithLetter(String str, String word, String c) {
StringBuilder result = new StringBuilder();
int index = 0;
while (index < str.length() )
{
String x = str.substring(index, Math.min(index + word.length(), str.length()));
if (x.equals(word))
{
result.append(c);
index = index + word.length();
}
//If we aren't replacing, only add one char
else {
result.append(x.charAt(0));
index++;
}
}
if (str.length() > index)
{
result.append(str.substring(index, str.length() - index));
}
return result.toString();
}
Found the fix to my issue using #GBlodgett's code:
String result = "";
int index = 0;
while (index <= str.length() - word.length() )
{
String x = str.substring(index, index + word.length() );
if (x.equals(word))
{
result = result + c;
index = index + word.length();
}
else {
result = result + x.charAt(0);
index++;
}
}
if (str.length() < index + word.length())
{
result = result + (str.substring(index));
}
return result;
}
You can use String.replaceAll() method.
example:
public class StringReplace {
public static void main(String[] args) {
String str = "aaaaaaaa";
String fnd = "aaa";
String rep = "w";
System.out.println(str.replaceAll(fnd, rep));
System.out.println("asdfdsdfjsdf".replaceAll("sdf", "q"));
}
}
Output:
wwaa
aqdqjq
I am trying to make a program to find the number of characters of the longest palindrome within a word. What the program does is find all different substrings of the given string and should check if its a palindrome and then the number of characters it has.
Right now it is correctly finding all possible substrings and works if I enter an actual palindrome such as hannah, but if i input something like banana, I get the following error StringIndexOutOfBoundsException.
Here is my code:
import java.util.Scanner;
public class Palindrome {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String word;
String reverseWord;
int palindromeLength = 0;
System.out.print("Enter A Word: ");
word = sc.nextLine();
reverseWord = new StringBuffer(word).reverse().toString();
if (reverseWord.equals(word))
palindromeLength = word.length();
else {
for(int i = 0; i < word.length(); i++) {
for(int j = 1; j <= word.length() - j; j++) {
String substring = word.substring(i, i + j);
String reverseSubstring = new StringBuffer(substring).reverse().toString();
if (reverseSubstring.equals(substring)) {
if (substring.length() > palindromeLength) {
palindromeLength = substring.length();
}
}
}
}
}
System.out.println(palindromeLength);
}
}
Anyone know why this is happening and how I could fix the issue?
Thanks!
This is where the exception occurs (because endIndex is larger than the length of the string):
String substring = word.substring(i, i + j);
Use this instead:
String substring = word.substring(i, word.length());
It prints out 5 for "banana" which is expected behaviour.
Here is my solution:
class Palindrome {
public static void main(String[] args) {
System.out.println(longestPalindrome("" +
"A man once told me, " +
"\"A man, a plan, a canal, Panama!\" " +
"But what does that mean?"));
System.out.println(longestPalindrome("" +
"And then he said, " +
"\"No 'x' in Nixon\"... " +
"Wtf?"));
}
private static int longestPalindrome(final String word) {
assert word != null;
final String sanitized = word
.replaceAll("\\W", "")//strip non-word chars
.toLowerCase();
int currentWinner = 0;
for (int i = 0; i < sanitized.length(); i++) {
//odd palindromes
currentWinner = Math.max(detectPalindrome(sanitized, i, 0, 0), currentWinner);
//even palindromes
currentWinner = Math.max(detectPalindrome(sanitized, i, 0, -1), currentWinner);
}
return currentWinner;
}
private static int detectPalindrome(final String word,
final int center,
final int currentIndex,
final int polarity) {
final int left = center - currentIndex;
final int right = center + currentIndex + 1 + polarity;
if (left >= 0
&& right < word.length()
&& word.charAt(left) == word.charAt(right)) {
//if you're still on the string and the streak holds, check the next char
return (detectPalindrome(word, center, currentIndex + 1, polarity));
} else {
//else return the longest found so far
return currentIndex * 2 + polarity;
}
}
}
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)));
}
I'm trying to find the shortest palindrome that one can create from S by by adding 0 or more characters in front of it. For example the shortest palindrome can be constructed from 'baaa' is 'aaabaaa'. The two functions that I'm using are given below. This works for this case for doesn't yield the shortest result in all cases.
public static boolean checkPalindrome(String s){
for (int i = 0; i < s.length()/2; i++) {
if (s.charAt(i) != s.charAt(s.length() - i - 1)) return false;
}
return true;
}
public static int makePalindrome(String s){
int min = 0;
StringBuilder str = new StringBuilder(s);
for (int i = 1; i < s.length() ; i++) {
str.insert(0, s.charAt(i));
if (checkPalindrome(str.toString()) == true) {
min = str.length();
break;
}
}
return min;
}
I can't seem to figure out what logical step am I missing.
Your helper method checkPalindrome seems correct. Your thinking is also correct (append characters until the result is a palindrome), but the way you're going about it is wrong.
To reiterate: Our logic is, while our result is not a palindrome, take the next character from the end (moving towards the start of the string) and append it to the prefix. So for the string "abcd", we would try
"" + "abcd" -> "abcd" -> false
"d" + "abcd" -> "dabcd" -> false
"dc" + "abcd" -> "dcabcd" -> false
"dcb" + "abcd" -> "dcbabcd" -> true, terminate
Here's a fixed version:
public static String makePalindrome(String base){
String pref = "";
int i = base.length() - 1;
while(! checkPalindrome(pref + base)){
pref = pref + base.charAt(i);
i --;
}
return pref + base;
}
I am not sure i understand the question but from what i understood you want to turn Strings like Hello to olleHello To do this, loop trhough each char of the string with like:
String example = "Hello There Mate"; //our string
StringBuilder exampleBuilder = new StringBuilder();
for(int i=example.length()-1; i>0; i--)
exampleBuilder.append(example.charAt(i));
//Our loop, the reason why it is example.lenght-1
//is because we want the first letter to appear only
//1 time :)
String finalString = exampleBuilder.toString()+example;
//The final string, should be 'olleHello'
System.out.println(finalString);
Hope thats what you are looking for :D
IDEONE: http://ideone.com/tawjmG
We can find the shortest Palindrome using the following logic:
Find the midpoint, loop from 0 to midpoint, length-1 to midpoint.
If palindrome, return
If not palindrome, add 1 to midpoint, do same logic
In code:
static String shortestPalindrome(String s) {
if (s.length() == 1) return s;
return recShortestPalindrome(s, s.length()>>1, 0);
}
static String recShortestPalindrome(String s, int mid, int add) {
// AABBA[X]
int fakeLen = s.length() + add;
for (int i = 0; i < mid; i++) {
char c1 = s.charAt(i);
int p1 = fakeLen - 1 - i;
if (p1 < s.length()) {
char c2 = s.charAt(p1);
if (c2 != c1) {
return recShortestPalindrome(s, mid+1, add+1);
}
}
}
// found a pattern that works
String h1 = s.substring(0, mid);
String h2 = new StringBuilder(h1).reverse().toString();
String ret = h1+h2;
int midPoint = ret.length()/2;
if (ret.length()%2 == 0 && ret.length() >= 2) {
char c1 = ret.charAt(midPoint);
char c2 = ret.charAt(midPoint-1);
if (c1 == c2) {
return ret.substring(0, midPoint) + ret.substring(midPoint+1, ret.length());
}
}
return h1+h2;
}
Python Solution:
def isPalindrome(x):
if x == "":
return False
r = ""
r = str(x)
r = r[::-1]
return True if x == r else False
def makePalindrome(my_str):
pref = ""
i = len(my_str) - 1
while isPalindrome(pref + my_str) == False:
pref = pref + my_str[i]
i -= 1
return pref + my_str
my_str = "abcd"
print(makePalindrome(my_str))
i have this assignment for school which ask us to write code to find the longest common Substring. I have done that, but it only works with text that are not so big and it is being asked to find the common substring for Moby Dick and War And Peace. If you could point me in the right direction of what i'm doing wrong, i would appreciate it. The compiler is complaining that the error is in the substring method of the MyString class when i call it to create the SuffixArray but idk why its saying its too big, giving me the outofmemory
package datastructuresone;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Scanner;
class SuffixArray
{
private final MyString[] suffixes;
private final int N;
public SuffixArray(String s)
{
N = s.length();
MyString snew = new MyString(s);
suffixes = new MyString[N];
for (int i = 0; i < N; i++)
{
suffixes[i] = snew.substring(i);
}
Arrays.sort(suffixes);
}
public int length()
{
return N;
}
public int index(int i)
{
return N - suffixes[i].length();
}
public MyString select(int i)
{
return suffixes[i];
}
// length of longest common prefix of s and t
private static int lcp(MyString s, MyString t)
{
int N = Math.min(s.length(), t.length());
for (int i = 0; i < N; i++)
{
if (s.charAt(i) != t.charAt(i))
{
return i;
}
}
return N;
}
// longest common prefix of suffixes(i) and suffixes(i-1)
public int lcp(int i)
{
return lcp(suffixes[i], suffixes[i - 1]);
}
// longest common prefix of suffixes(i) and suffixes(j)
public int lcp(int i, int j)
{
return lcp(suffixes[i], suffixes[j]);
}
}
public class DataStructuresOne
{
public static void main(String[] args) throws FileNotFoundException
{
Scanner in1 = new Scanner(new File("./build/classes/WarAndPeace.txt"));
Scanner in2 = new Scanner(new File("./build/classes/MobyDick.txt"));
StringBuilder sb = new StringBuilder();
StringBuilder sb1 = new StringBuilder();
while (in1.hasNextLine())
{
sb.append(in1.nextLine());
}
while (in2.hasNextLine())
{
sb1.append(in2.nextLine());
}
String text1 = sb.toString().replaceAll("\\s+", " ");
String text2 = sb1.toString().replaceAll("\\s+", " ");
int N1 = text1.length();
int N2 = text2.length();
SuffixArray sa = new SuffixArray(text1 + "#" + text2);
int N = sa.length();
String substring = "";
for (int i = 1; i < N; i++)
{
// adjacent suffixes both from second text string
if (sa.select(i).length() <= N2 && sa.select(i - 1).length() <= N2)
{
continue;
}
// adjacent suffixes both from first text string
if (sa.select(i).length() > N2 + 1 && sa.select(i - 1).length() > N2 + 1)
{
continue;
}
// check if adjacent suffixes longer common substring
int length = sa.lcp(i);
if (length > substring.length())
{
substring = sa.select(i).toString().substring(0, length);
System.out.println(substring + " ");
}
}
System.out.println("The length of the substring " + substring.length() + "length on first N " + N1 + " length of Second N " + N2
+ "The length of the array sa: " + N);
System.out.println("'" + substring + "'");
final class MyString implements Comparable<MyString>
{
public MyString(String str)
{
offset = 0;
len = str.length();
arr = str.toCharArray();
}
public int length()
{
return len;
}
public char charAt(int idx)
{
return arr[ idx + offset];
}
public int compareTo(MyString other)
{
int myEnd = offset + len;
int yourEnd = other.offset + other.len;
int i = offset, j = other.offset;
for (; i < myEnd && j < yourEnd; i++, j++)
{
if (arr[ i] != arr[ j])
{
return arr[ i] - arr[ j];
}
}
// reached end. Who got there first?
if (i == myEnd && j == yourEnd)
{
return 0; // identical strings
}
if (i == myEnd)
{
return -1;
} else
{
return +1;
}
}
public MyString substring(int beginIndex, int endIndex)
{
return new MyString(arr, beginIndex + offset, endIndex - beginIndex);
}
public MyString substring(int beginIndex)
{
return substring(beginIndex, offset + len);
}
public boolean equals(Object other)
{
return (other instanceof MyString) && compareTo((MyString) other) == 0;
}
public String toString()
{
return new String(arr, offset, len);
}
private MyString(char[] a, int of, int ln)
{
arr = a;
offset = of;
len = ln;
}
private char[] arr;
private int offset;
private int len;
}
Here:
for (int i = 0; i < N; i++)
{
suffixes[i] = snew.substring(i);
}
You are trying to store, not only the entire long string, but the entire string - 1 letter, and the entire string - 2 letters, etc. All of these are stored separately.
If your String were only 10 letters, you would be storing a total of 55 characters worth in 10 different string.
At 1000 characters, you are storing 500500 characters total.
More generally, you are having to handle, length*(length+1)/2 characters.
Just for fun, I don't know how many characters are in War and Peace, but with a page count around 1250, a typical words/page estimate being 250, and the average word being about 5 characters long, comes to:
(1250 * 250 * 5)*(1250 * 250 * 5 + 1)/2 = 1.2207039 * 10^12 characters.
The size of a char in memory being 2 bytes, so you're looking at about 2.22 TB in size (compared to 1.49 MB for just the text of the novel).
I count at least 3 copies of both texts in the first few lines of the code. Here's a few ideas
convert the spaces as you read each line in--not after they are huge strings. Don't forget the case of spaces at the front and end of lines.
build your MyString class using StringBuilder as the base instead of String. Do all the looking inside the StringBuilder with its native methods, if you can.
don't extract strings any more than you have to.
Look up the -Xmx java runtime option and set the heap space large than the default. You'll have to google this as I don't have it memorized. Just notice that -Xmx=1024M needs that M at the end. (Look at the file size to see how big the two books are.)
When you construct MyString, you call arr = str.toCharArray(); which makes a new copy of the string's character data. But in Java, a string is immutable - so why not store a reference to the string instead of a copy of its data?
You construct every suffix at once, but you only refer to one (well, two) at a time. If you recode your solution to only reference the suffixes it currently cares about, and construct them only when it needs them (and lose a reference to them afterwards), they can be garbage collected by Java. This will make running out of memory less likely. Compare the memory overhead of storing 2 strings to storing hundreds of thousands of strings :)
I wrote this program in Scala. Maybe you can translate it to Java.
class MyString private (private val string: String, startIndex: Int, endIndex: Int) extends Comparable[MyString] {
def this(string: String) = this(string, 0, string.length)
def length() = endIndex-startIndex
def charAt(i: Int) = {
if(i >= length) throw new IndexOutOfBoundsException
string.charAt(startIndex + i)
}
def substring(start: Int, end: Int): MyString = {
if(start < 0 || end > length || end < start) throw new IndexOutOfBoundsException
new MyString(string, startIndex + start, startIndex + end)
}
def substring(start: Int): MyString = substring(start, length)
def longestCommonSubstring(other: MyString): MyString = {
var index = 0
val len = math.min(length, other.length)
while(index < len && charAt(index) == other.charAt(index)) index += 1
substring(0, index)
}
def compareTo(other: MyString): Int = {
val len = math.min(length, other.length)
for(i <- 0 until len) {
if(charAt(i) > other.charAt(i)) return 1
if(charAt(i) < other.charAt(i)) return -1
}
length-other.length
}
def >(other: MyString) = compareTo(other) > 0
def <(other: MyString) = compareTo(other) < 0
override def equals(other: Any) = other.isInstanceOf[MyString] && compareTo(other.asInstanceOf[MyString]) == 0
override def toString() = "\"" + string.substring(startIndex, endIndex) + "\""
}
def readFile(name: String) = new MyString(io.Source.fromFile(name).getLines.mkString(" ").replaceAll("\\s+", " "))
def makeList(str: MyString) = (0 until str.length).map(i => str.substring(i)).toIndexedSeq
val string1 = readFile("WarAndPeace.txt")
val string2 = readFile("MobyDick.txt")
val (list1, list2) = (makeList(string1).sorted, makeList(string2).sorted)
var longestMatch = new MyString("")
var (index1, index2) = (0,0)
while(index1 < list1.size && index2 < list2.size) {
val lcs = list1(index1).longestCommonSubstring(list2(index2))
if(lcs.length > longestMatch.length) longestMatch = lcs
if(list1(index1) < list2(index2)) index1 += 1
else index2 += 1
}
println(longestMatch)