Sunday, 2 March 2014




UVA 941 PERMUTATION

Rank of a  given String - In a Lexicographic taste- 
Lexicographic style deals with dictionary style arrangement of characters.
The Rank of a particular arrangement  of characters of a string pretains to a particular permutation adhering to lexicographic arrangement

Taking an example of a given string "abc" , the rank of "abc" would be 1 - lexicographically
Similarly-
abc = 1
acb = 2
cba = 6

The simplest solution that strikes in mind is to take out all lexicographic permutation of the given string and then 
iterate over all permuataions until we find our given match , incrementing passing by every term.

This solution can make complexity increasing exponentially in worst case  :P


The efficient solution is  somewhat tricky , just some high school math work- 
Let the given string be " JIM"  
Check first character "J"  
Total characters = 5
Character smaller then "J" = "I" i.e 1
So there can be 1*2! strings , which have first character smaller then "J" - 
IXX

Now fixing "J" we gotta find smaller strings  starting with "J"
Next character "I" have no character smaller then itself so zero in this case with total rank 1*2!+ 0*1!+...
Next character "M"  have no character smaller then itself so zero in this case with total rank 1*2!+ 0*1!+0*1!..

So rank = 1*2!+ 0*1!+0*0!= 2
As rank starts from 1 unlike numbering starting from zero in programming so rank of "JIM" = 2+1= 3

NOTE- 
To calculate the Lexicographic permuatation for repeated characters, just follow same procedure and in end divide the rank with p! where p is count of occurence of each repeated character . eg-  rank/2! in case of  string  "JIMMY "

//******************* codebloodedvalley.blogspot.com *********************
// ******************  1:24 AM  03-03-2014, GNDU RC SATHIALA *************
#include<stdio.h>
#include<string.h>
#define MAX_CHAR 256

// utility function to find n factorial
int fact(int n){
return (n<=1) ? 1 : n * fact(n-1) ; 
}

// an array count where value at each index gonna 
// contain total count of smaller characters present in given string

void  increaseCountbyPopulating (int* count ,  char* str){
int i;
for(i=0;str[i];++i) // populating  count of each character
++count[ str[i] ];

// instead of calling a loop again n again to check the total characters smaller then particular 
//character present , just iterate once and add the preceding value in every next count[i] for  i <=256
// This will help us to straightway accessing the total numbers of of character smaller then count[str[i]] as shown
// later in the rankFinder() . 
// Unexpected , but Dont panic :D

for(i=1;i<256;++i)  
count[i]+=count[i-1];


}
void countUpdate(int* count, char ch){        // this function is fixing the value of character as explained above
// by deleting its every  occurence in count[] 
int i;
for(i=ch;i<MAX_CHAR;++i)
--count[i];


}

//  now checkout the function to find the rank,pretty simple, understand afformentioned point carefully 
int rankFinder(char* str){
int len =  strlen(str);
int mul = fact(len);
int rank = 1, i;

int count[MAX_CHAR] = {0}; // initialising all elements to 0

 // populating count[i] having count of characters smaller then i present in given string
 increaseCountbyPopulating(count,str);
  for (i = 0; i < len; ++i)
    {
        mul /= len - i;  // this is tricky and efficient, simple high school maths

        // count number of chars smaller than str[i]
        // from str[i+1] to str[len-1]
        rank += count[ str[i] - 1] * mul;

        // Reduce count of characters greater than str[i], i.e fixing the occurence of string[i]
        countUpdate (count, str[i]);
    }

    return rank;
}

// Driver program 
int main()
{
    char str[] = "JIM";
int rank= rankFinder(str);  
printf ("%d", rank);
    return 0;
}























No comments:

Post a Comment