bool function problem - always returns true? - c++

#include <iostream>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
using namespace std;
static bool isanagram(string a, string b);
int main(void)
{
int i,n,j,s;
cin >> n;
string a, b;
cin >> a >> b;
if(!isanagram(a,b)) cout << "False" << endl;
else cout << "True" << endl;
return 0;
}
static bool isanagram(string a, string b)
{
int i, j, size, s=0;
size = a.size();
bool k;
for(i=0;i<size;i++)
{
k=false;
for(j=0;j<size;j++)
{
if(a[i] == b[j]) { k = true; break; }
}
if(k==true) s+=1;
}
cout << a[2] << b[2] << endl;
if(s == size) return true;
else return false;
}
I don't know where exactly is the problem so i just pasted the whole code.
It should be a simple program capable for finding if two strings are anagrams, but it's not working and i don't know why. I used pointers in the program so thought the might be the problem and removed them, i removed other things additionally but still it's not working. If you can give it a look-see and tell me some idea where i might've gone wrong with my code ?
Thank you in advance.

The logic for your isanagram function is fatally flawed - it will never work correctly, even if you manage to fix the bugs in it.
You need to make sure that you have a correct algorithm before you start coding. One simple algorithm might be:
sort a
sort b
isanagram = (a == b)

It's not always return true:
Here's my input:
0
sdf
fda
Here's output I got:
fa
False
Regarding your task: if performance is not an issue for you task, just sort 2 strings (using std::sort) and compare results.
Regarding your style:
use string::length() instead of size() -- it's more idiomatic
instead of if(s == size) return true; else return false; consider return s == size
pass your strings by const reference, not by value
consider declaring variables as close to point of their usage as possible (but not closely) and initialize them when declaring (i, j, k, size all fit this hint)

Your approach is fine but it has a small flaw. You ensuring that every char from string a is present in string. So if a = "aab" and b = "abc", your approach will flag them as anagram. You also need to take the count of char in account.
The definition of anagram is:
An anagram is a type of word play, the result of rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once;
Easiest way as many have suggested is to ensure that the strings are of the same length . If they are, sort the two string and check for equality.
If you want to patch your approach, you can make the char in string b NULL after it has been matched with a char in string a.
Something like:
if(a[i] == b[j]) { b[j] = 0; k = true; break; }
in place of your:
if(a[i] == b[j]) { k = true; break; }
This way once a char of b has been matched it cannot participate again.

There are essentially two ways of checking for anagrams:
Sort both strings and see if they match. If they are anagrams, they will both have the same letters and a sort would order them into the same sequence.
Count the frequency of each char in each string. If they are anagrams, the frequency counts for each char will be the same for both strings.

First things first: don't declare the method static. It's a confusing keyword at the best of times given all the roles it can fulfill... so reserve for times when you really have to (method or attribute of a class that is not tied to any instance for example).
Regarding the algorithm: you're nearly there, but presence only is not sufficient, you need to take the number of characters in account too.
Let's do it simply:
bool anagram(std::string const& lhs, std::string const& rhs)
{
if (lhs.size() != rhs.size()) return false; // does not cost much...
std::vector<int> count(256, 0); // count of characters
for (size_t i = 0, max = lhs.size(); i != max; ++i)
{
++count[lhs[i]];
--count[rhs[i]];
}
for (size_t i = 0, max = count.size(); i != max; ++i)
if (count[i] != 0) return false;
return true;
} // anagram
Let's see it at work: anagram("abc","cab")
Initialization: count = [0, 0, ...., 0]
First loop i == 0 > ['a': 1, 'c': -1]
First loop i == 1 > ['a': 0, 'b': 1, 'c': -1]
First loop i == 2 > ['a': 0, 'b': 0, 'c': 0 ]
And the second loop will pass without any problem.
Variants include maintaining 2 counts arrays (one for each strings) and then comparing them. It's slightly less efficient... does not really matter though.
int main(int argc, char* argv[])
{
if (argc != 3) std::cout << "Usage: Program Word1 Word2" << std::endl;
else std::cout << argv[1] << " and " << argv[2] << " are "
<< (anagram(argv[1], argv[2]) ? "" : "not ")
<< "anagrams" << std::endl;
}

I see some problems with your code. Basically the algorithm is wrong. It will match characters within a.size(). It takes no account for duplicates (in either a or b).
Essentially, you should sort the strings and then compare for equality.
If you can't sort, at least remove the b characters from the comparison, eliminate the k variable.

Related

This is an anagram program where I am checking if two same length strings are anagram to each other

The if statement doesn't terminate the while loop for some reason, which results in unwanted outputs (more than one output). I hope someone can help. Thanks.
my code
I think you should return false inside if. Try this code.
#include <bits/stdc++.h>
using namespace std;
bool areAnagram(string str1, string str2)
{
int n1 = str1.length();
int n2 = str2.length();
if (n1 != n2)
return false;
sort(str1.begin(), str1.end());
sort(str2.begin(), str2.end());
for (int i = 0; i < n1; i++)
if (str1[i] != str2[i])
return false;
return true;
}
int main()
{
string str1 = "test";
string str2 = "ttew";
if (areAnagram(str1, str2))
cout << "The two strings are anagram of each other";
else
cout << "The two strings are not anagram of each other";
return 0;
}
First, your if statement doesn't break the inner loop. That means that you would output the phrase "NOT ANAGRAM" the number of times the sorted arrays differ. Actually, the number of times minus one (probably), because of the second: the inner loop compares one element less than it should. You should iterate upto i < len.
Third, doesn't matter if it is an anagram or not, the program will always output "ANAGRAM" at the end because you set bool_ = false right after this output.
#tash29 and #D.Khumoyun
std::string has a == operator. You can compare a string by simply writing if (a == b). There is no need for byte wise comparison.
If you use the C++ ternary conditional operator, you can do everything important in one line.
I am sorry, the task is too simple, I cannot explain more . . .
Please see:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string a = "ajar";
std::string b = "stag";
std::sort(a.begin(), a.end());
std::sort(b.begin(), b.end());
std::cout << ((a == b) ? "Anagram" : "Not Anagram");
return 0;
}

How to find first set?

I am trying to list the First set of a given grammar with this function:
Note:
char c - the character to find the first set;
first_set - store elements of the corresponding first set;
q1, q2 - the previous position;
rule- store all the grammar rule line by line listed below;
for the first time the parameters are ('S', 0, 0).
void findfirst(char c, int q1, int q2){
if(!(isupper(c)) || c=='$'){
first_set[n++] = c;
}
for(int j=0;j<rule_number;j++){
if(rule[j][0]==c){
if(rule[j][2]==';'){
if(rule[q1][q2]=='\0')
first_set[n++] = ';';
else if(rule[q1][q2]!='\0' &&(q1!=0||q2!=0))
findfirst(rule[q1][q2], q1, (q2+1));
else
first_set[n++] = ';';
}
else if(!isupper(rule[j][2]) || rule[j][2]=='$')
first_set[n++] = rule[j][2];
else
findfirst(rule[j][2],j,3);
}
}
}
But found that if the given grammar looks like this:
S AC$
C c
C ;
A aBCd
A BQ
B bB
B ;
Q q
Q ;
(which the left hand side or any capital letters in the right hand side are non-terminal, and any small case letters are terminal)
the function couldn't correctly output the first set for S, since it will stop at finding the first set of Q and store ';' to the first set and won't go on to find C's first set.
Does anyone have a clue? Thanks in advance.
It is extremely inefficient to compute FIRST sets one at a time, since they are interdependent. For example, in order to compute the FIRST set of A , you need to also compute the FIRST set of B, and then because B can derive the emoty string, you need the FIRST set of Q.
Most algorithms compute all of them in parallel, using some variation of a transitive closure algorithm. You can do this with a depth-first search, which seems to be what you are attempting, but it might be easier to implement the least fixed point algorithm described in the Dragon book (and Wikipedia.
Either way, you will probably find it easier to first compute NULLABLE (that is, which non-terminals derive the empty set). There is a simple linear-time algorithm for that (linear in the size of the grammar), which again is easy to find.
If you are doing this work as part of a class, you'll probably find the relevant algorithms in your course materials. Alternatively, you can look for a copy of the Dragon book or other similar text books.
You could do like the following code:
used[i] means the rule[i] is used or not
The method is Depth-first search, see https://en.wikipedia.org/wiki/Depth-first_search
#include <iostream>
#define MAX_SIZE 1024
char rule[][10] = {
"S AC$",
"C c",
"C ;",
"A aBCd",
"A BQ",
"B bB",
"B ;",
"Q q",
"Q ;"
};
constexpr int rule_number = sizeof(rule) / sizeof(rule[0]);
char first_set[MAX_SIZE];
bool findfirst(int row, int col, int *n, bool* used) {
for (;;) {
char ch = rule[row][col];
if (ch == '$' || ch == ';' || ch == '\0') {
first_set[*n] = '\0';
break;
}
if (islower(ch)) {
first_set[(*n)++] = ch;
++col;
continue;
}
int i;
for (i = 0; i != rule_number; ++i) {
if (used[i] == true || rule[i][0] != ch)
continue;
used[i] = true;
int k = *n;
if (findfirst(i, 2, n, used) == true)
break;
used[i] = false;
*n = k;
}
if (i == rule_number)
return false;
++col;
}
return true;
}
int main() {
bool used[rule_number];
int n = 0;
for (int i = 2; rule[0][i] != '$' && rule[0][i] != '\0'; ++i) {
for (int j = 0; j != rule_number; ++j)
used[j] = false;
used[0] = true;
findfirst(0, i, &n, used);
}
std::cout << first_set << std::endl;
return 0;
}

How do you check if content of string starts with the content of another string?

I'm trying to figure out if there is a way to compare if a content of a string is the start of another string. For example, I want to know the number of strings that start with the string "c", in an array whose content's is [cowboy, air, cow, cat]. Using the compare function from the string library works fine. The issue is when instead of trying with "c", I try with "b" I get the same number of answers. I don't know the reason why, Does anybody have a suggestion on how to fix the problem? Here are the two versions that I have.
#include <iostream>
#include <string>
using namespace std;
int main() {
// insert code here...
string A[4] = {"cowboy", "air", "c", "count"};
string b = "c";
int count = 0;
for(int i = 0; i < 4; i++)
{
if(b.compare(A[i]) == 0 || b.compare(A[i]) == -1)
count++;
}
cout << count << endl;
}
The output for this part is 3, which is right
#include <iostream>
#include <string>
using namespace std;
int main() {
// insert code here...
string A[4] = {"cowboy", "air", "c", "count"};
string b = "b";
int count = 0;
for(int i = 0; i < 4; i++)
{
if(b.compare(A[i]) == 0 || b.compare(A[i]) == -1)
count++;
}
cout << count << endl;
}
The output for this part is also 3, which is wrong.
Any help would be really appreciated!
There is an overload of the compare function which accepts position and a length, and compares only a part of the string to the other string. If you pass 0 for the position, and the size of the string you are searching for as the length, it will only compare that many characters at the start of the string, instead of comparing the whole thing.
if(A[i].compare(0, b.size(), b) == 0)
count++;
By the way, the only reason your first test appeared to be working, was that you were basically checking if "c" is lexicographically less than or equal to your target strings. And since that is the case for "cowboy", "c" and "count", but not "air", your result was 3. But if you added a string like, "direwolf", which comes lexicographically after "c", but does not start with "c", you would find that your results were not what you are expecting.
You can try using the find function:
string A[4] = {"cowboy", "air", "c", "count"};
string b = "b";
int count = 0;
for(int i = 0; i < 4; i++)
{
auto found = A[i].find(b);
if(found != string::npos && found == 0)
count++;
}
cout << count << endl;
What I do here is find b in A[i], if I get npos which means it wasn't found if I do find it, I check if its at the start by checking found == 0
Similarly to simplify if I only want to check for just a character match at the start I could simply A[i] == b[0]
Live Demo
Replace your if condition with the following. This compares the string b with A[i]'s 1st character.
if(b.compare(0, A[i].length(), A[i], 0, 1) == 0)
In your for loop when you pass in b = "c" the first conditions satisfies b.compare(A[i]) == 0 and for b="a" second condition satisfies. So in both cases you see 3.
You can do it easily by changing string b to character b and then checking if the first letter of each string in the array is equal to b or not and incrementing the count when they are equal.

Using vectors to solve the anagrams in C++

I have a function that takes in two vectors of strings and compares each element to see if they are anagrams of one another.
Vector #1: "bat", "add", "zyz", "aaa"
Vector #2: "tab", "dad", "xyx", "bbb"
Restrictions and other things to clarify: The function is supposed to loop through both vectors and compare the strings. I am only supposed to compare based on the index of each vector; meaning I only compare the strings which are in the first index, then the strings which are in the second index, and so on. It's safe to assume that the vectors passed in as parameters will always be the same size.
If the compared strings are anagrams, "Match" is printed on the screen. If they aren't, "No Match" is printed.
Output: Match Match No Match No Match
I'm getting ridiculously stuck on this problem, I know how to reverse strings but when it gets to this I'm getting a bit clueless.
I understand that I would need to iterate through each vector, and then compare. But how would I be able to compare each letter within the string? Also, I'm not allowed to include anything else like algorithm, sort, or set. I've tried digging through a lot of questions but most answers utilized this.
If there are any tips on how to solve this, that would be great. I'll be posting what I find shortly.
Here's what I got so far:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void anagrams(const vector<string>& vOne, const vector<string>& vTwo){
for(int i=0; i< vOne.size(); i++){
for(int j=0; j< vTwo.size(); j++){
if(vOne[i].size() != vTwo[j].size()){
cout << 0 << endl;
}
else {
cout << 1 << endl;
}
}
}
}
void quicksort(vector<int>& a, int low, int high){
if(low < high)
{
int mid = (low + high)/2;
int pivot = a[mid];
swap(a[high], a[mid]);
int i, j;
for(i=low, j=high-1; ;){
while(a[i]<pivot) ++i;
while(j>i && pivot < a[j]) --j;
if (i < j)
swap(a[i++], a[j--]);
else
break;
}
swap(a[i], a[high]);
}
quicksort(a, low, i - 1);
quicksort(a, i + 1, high);
}
Thanks in advance!
Though you are not able to use sort, you should still sort the the words you are checking against, to see if they are anagrams. You will just have to sort the char[] manually, which is unfortunate, yet a good exercise. I would make a predicate, a function that compares the 2 strings and return true or false, and use that to check if they are anagrams. Also, it seems as though you don't need to print out both words that actually match, if that is true, then you can sort the words in the vectors when you first read them in, then just run them through your predicate function.
// Predicate
bool isMatch(const string &lhs, const string &rhs)
{
...sort and return lhs == rhs;
}
If you write the function, as I have above, you are passing in the parameters by const reference, which then you can copy (not using strcpy() due to vulnerabilities) the parameters into char[] and sort the words. I would recommend writing your sort as its own function.
Another hint, remember that things are much faster, and stl uses smart ptrs to do sorting. Anyway, I hope this helps even a little bit, I didn't want to give you the answer.
A solution that is fairly quick as long as the strings only contain characters between a-z and A-Z would be
bool is_anagram( const string& s1, const string& s2 ) {
if( s1.size() != s2.size() ) {
return false;
}
size_t count[ 26 * 2 ] = { 0 };
for( size_t i = 0; i < s1.size(); i++ ) {
char c1 = s1[ i ];
char c2 = s2[ i ];
if( c1 >= 'a' ) {
count[ c1 - 'a' ]++;
}
else {
count[ c1 - 'A' + 26 ]++;
}
if( c2 >= 'a' ) {
count[ c2 - 'a' ]--;
}
else {
count[ c2 - 'A' + 26 ]--;
}
}
for( size_t i = 0; i < 26 * 2; i++ ) {
if( count[ i ] != 0 ) {
return false;
}
}
return true;
}
If you're willing to use C++11, here is some rather inefficient code for seeing if two strings are anagrams. I'll leave it up to you to loop through the list of words.
#include <iostream>
#include <vector>
using namespace std;
int count_occurrences(string& word, char search) {
int count = 0;
for (char s : word) {
if (s == search) {
count++;
}
}
return count;
}
bool compare_strings(string word1, string v2) {
if (word1.size() != v2.size())
{
return false;
}
for (char s: word1) //In case v1 contains letters that are not in v2
{
if (count_occurrences(word1, s) != count_occurrences(v2, s))
{
return false;
}
}
return true;
}
int main() {
string s1 = "bat";
string s2 = "atb";
bool result = compare_strings(s1, s2);
if (result)
{
cout << "Match" << endl;
}
else
{
cout << "No match" << endl;
}
}
This works by simply counting the number of times a given letter occurs in a string. A better way to do this would be to sort the characters in the string alphabetically, and then compare the sorted strings to see if they are equal. I'll leave it up to you to improve this.
Best wishes.
Another solution, since I'm sufficiently bored:
#include <iostream>
#include <vector>
#include <string>
int equiv_class(char c) {
if ((c>='A')&&(c<='Z')) return c-'A';
if ((c>='a')&&(c<='z')) return c-'a';
return 27;
}
bool is_anagram(const std::string& a, const std::string& b)
{
if (a.size()!=b.size()) return false;
int hist[26]={};
int nz=0; // Non-zero histogram sum tally
for (int i=0, e=a.size() ; i!=e ; ++i)
{
int aclass = equiv_class(a[i]);
int bclass = equiv_class(b[i]);
if (aclass<27) {
switch (++hist[aclass]) {
case 1: ++nz; break; // We were 0, now we're not--add
case 0: --nz; break; // We were't, now we are--subtract
// otherwise no change in nonzero count
}
}
if (bclass<27) {
switch (--hist[bclass]) {
case -1: ++nz; break; // We were 0, now we're not--add
case 0: --nz; break; // We weren't, now we are--subtract
// otherwise no change in nonzero count
}
}
}
return 0==nz;
}
int main()
{
std::vector<std::string> v1{"elvis","coagulate","intoxicate","a frontal lobotomy"};
std::vector<std::string> v2{"lives","catalogue","excitation","bottlein frontofme"};
for (int i=0, e=(v1.size()==v2.size()?v1.size():0); i!=e; ++i) {
if (is_anagram(v1[i],v2[i])) {
std::cout << " Match";
} else {
std::cout << " No Match";
}
}
}

How many palindromes can be formed by selections of characters from a string?

I'm posting this on behalf of a friend since I believe this is pretty interesting:
Take the string "abb". By leaving out
any number of letters less than the
length of the string we end up with 7
strings.
a b b ab ab bb abb
Out of these 4 are palindromes.
Similarly for the string
"hihellolookhavealookatthispalindromexxqwertyuiopasdfghjklzxcvbnmmnbvcxzlkjhgfdsapoiuytrewqxxsoundsfamiliardoesit"
(a length 112 string) 2^112 - 1
strings can be formed.
Out of these how many are
palindromes??
Below there is his implementation (in C++, C is fine too though). It's pretty slow with very long words; he wants to know what's the fastest algorithm possible for this (and I'm curious too :D).
#include <iostream>
#include <cstring>
using namespace std;
void find_palindrome(const char* str, const char* max, long& count)
{
for(const char* begin = str; begin < max; begin++) {
count++;
const char* end = strchr(begin + 1, *begin);
while(end != NULL) {
count++;
find_palindrome(begin + 1, end, count);
end = strchr(end + 1, *begin);
}
}
}
int main(int argc, char *argv[])
{
const char* s = "hihellolookhavealookatthis";
long count = 0;
find_palindrome(s, strlen(s) + s, count);
cout << count << endl;
}
First of all, your friend's solution seems to have a bug since strchr can search past max. Even if you fix this, the solution is exponential in time.
For a faster solution, you can use dynamic programming to solve this in O(n^3) time. This will require O(n^2) additional memory. Note that for long strings, even 64-bit ints as I have used here will not be enough to hold the solution.
#define MAX_SIZE 1000
long long numFound[MAX_SIZE][MAX_SIZE]; //intermediate results, indexed by [startPosition][endPosition]
long long countPalindromes(const char *str) {
int len = strlen(str);
for (int startPos=0; startPos<=len; startPos++)
for (int endPos=0; endPos<=len; endPos++)
numFound[startPos][endPos] = 0;
for (int spanSize=1; spanSize<=len; spanSize++) {
for (int startPos=0; startPos<=len-spanSize; startPos++) {
int endPos = startPos + spanSize;
long long count = numFound[startPos+1][endPos]; //if str[startPos] is not in the palindrome, this will be the count
char ch = str[startPos];
//if str[startPos] is in the palindrome, choose a matching character for the palindrome end
for (int searchPos=startPos; searchPos<endPos; searchPos++) {
if (str[searchPos] == ch)
count += 1 + numFound[startPos+1][searchPos];
}
numFound[startPos][endPos] = count;
}
}
return numFound[0][len];
}
Explanation:
The array numFound[startPos][endPos] will hold the number of palindromes contained in the substring with indexes startPos to endPos.
We go over all pairs of indexes (startPos, endPos), starting from short spans and moving to longer ones. For each such pair, there are two options:
The character at str[startPos] is not in the palindrome. In that case, there are numFound[startPos+1][endPos] possible palindromes - a number that we have calculated already.
character at str[startPos] is in the palindrome (at its beginning). We scan through the string to find a matching character to put at the end of the palindrome. For each such character, we use the already-calculated results in numFound to find number of possibilities for the inner palindrome.
EDIT:
Clarification: when I say "number of palindromes contained in a string", this includes non-contiguous substrings. For example, the palindrome "aba" is contained in "abca".
It's possible to reduce memory usage to O(n) by taking advantage of the fact that calculation of numFound[startPos][x] only requires knowledge of numFound[startPos+1][y] for all y. I won't do this here since it complicates the code a bit.
Pregenerating lists of indices containing each letter can make the inner loop faster, but it will still be O(n^3) overall.
I have a way can do it in O(N^2) time and O(1) space, however I think there must be other better ways.
the basic idea was the long palindrome must contain small palindromes, so we only search for the minimal match, which means two kinds of situation: "aa", "aba". If we found either , then expand to see if it's a part of a long palindrome.
int count_palindromic_slices(const string &S) {
int count = 0;
for (int position=0; position<S.length(); position++) {
int offset = 0;
// Check the "aa" situation
while((position-offset>=0) && (position+offset+1)<S.length() && (S.at(position-offset))==(S.at(position+offset+1))) {
count ++;
offset ++;
}
offset = 1; // reset it for the odd length checking
// Check the string for "aba" situation
while((position-offset>=0) && position+offset<S.length() && (S.at(position-offset))==(S.at(position+offset))) {
count ++;
offset ++;
}
}
return count;
}
June 14th, 2012
After some investigation, I believe this is the best way to do it.
faster than the accepted answer.
Is there any mileage in making an initial traversal and building an index of all occurances of each character.
h = { 0, 2, 27}
i = { 1, 30 }
etc.
Now working from the left, h, only possible palidromes are at 3 and 17, does char[0 + 1] == char [3 -1] etc. got a palindrome. does char [0+1] == char [27 -1] no, No further analysis of char[0] needed.
Move on to char[1], only need to example char[30 -1] and inwards.
Then can probably get smart, when you've identified a palindrome running from position x->y, all inner subsets are known palindromes, hence we've dealt with some items, can eliminate those cases from later examination.
My solution using O(n) memory and O(n^2) time, where n is the string length:
palindrome.c:
#include <stdio.h>
#include <string.h>
typedef unsigned long long ull;
ull countPalindromesHelper (const char* str, const size_t len, const size_t begin, const size_t end, const ull count) {
if (begin <= 0 || end >= len) {
return count;
}
const char pred = str [begin - 1];
const char succ = str [end];
if (pred == succ) {
const ull newCount = count == 0 ? 1 : count * 2;
return countPalindromesHelper (str, len, begin - 1, end + 1, newCount);
}
return count;
}
ull countPalindromes (const char* str) {
ull count = 0;
size_t len = strlen (str);
size_t i;
for (i = 0; i < len; ++i) {
count += countPalindromesHelper (str, len, i, i, 0); // even length palindromes
count += countPalindromesHelper (str, len, i, i + 1, 1); // odd length palindromes
}
return count;
}
int main (int argc, char* argv[]) {
if (argc < 2) {
return 0;
}
const char* str = argv [1];
ull count = countPalindromes (str);
printf ("%llu\n", count);
return 0;
}
Usage:
$ gcc palindrome.c -o palindrome
$ ./palindrome myteststring
EDIT: I misread the problem as the contiguous substring version of the problem. Now given that one wants to find the palindrome count for the non-contiguous version, I strongly suspect that one could just use a math equation to solve it given the number of distinct characters and their respective character counts.
Hmmmmm, I think I would count up like this:
Each character is a palindrome on it's own (minus repeated characters).
Each pair of the same character.
Each pair of the same character, with all palindromes sandwiched in the middle that can be made from the string between repeats.
Apply recursively.
Which seems to be what you're doing, although I'm not sure you don't double-count the edge cases with repeated characters.
So, basically, I can't think of a better way.
EDIT:
Thinking some more,
It can be improved with caching, because you sometimes count the palindromes in the same sub-string more than once. So, I suppose this demonstrates that there is definitely a better way.
Here is a program for finding all the possible palindromes in a string written in both Java and C++.
int main()
{
string palindrome;
cout << "Enter a String to check if it is a Palindrome";
cin >> palindrome;
int length = palindrome.length();
cout << "the length of the string is " << length << endl;
int end = length - 1;
int start = 0;
int check=1;
while (end >= start) {
if (palindrome[start] != palindrome[end]) {
cout << "The string is not a palindrome";
check=0;
break;
}
else
{
start++;
end--;
}
}
if(check)
cout << "The string is a Palindrome" << endl;
}
public String[] findPalindromes(String source) {
Set<String> palindromes = new HashSet<String>();
int count = 0;
for(int i=0; i<source.length()-1; i++) {
for(int j= i+1; j<source.length(); j++) {
String palindromeCandidate = new String(source.substring(i, j+1));
if(isPalindrome(palindromeCandidate)) {
palindromes.add(palindromeCandidate);
}
}
}
return palindromes.toArray(new String[palindromes.size()]);
}
private boolean isPalindrome(String source) {
int i =0;
int k = source.length()-1;
for(i=0; i<source.length()/2; i++) {
if(source.charAt(i) != source.charAt(k)) {
return false;
}
k--;
}
return true;
}
I am not sure but you might try whit fourier. This problem remined me on this: O(nlogn) Algorithm - Find three evenly spaced ones within binary string
Just my 2cents