/*
Online Java - IDE, Code Editor, Compiler

Online Java is a quick and easy tool that helps you to build, compile, test your programs online.
*/

//This is dealing with subsequence
//Need to remove all booleans since this is equivalent to a resilience check
//mantain a StringBuilder keeping track of all characters matched from String p
//also store the Window that is being searched.
//Perform a subtraction to get the longest subsequence
//Need to create else statement to char found to record characters not matched
//There is currently no track of index in String p..
//can use sb.length() and p.length() to ascertain index..


import java.util.*;
import java.math.BigInteger;

//These are the values when performing compareTo() on BigIntegers        
//1: when the first BigDecimal is greater than the second BigDecimal.
//0: when the first BigDecimal is equal to the second BigDecimal.
//-1: when the first BigDecimal is less than the second BigDecimal.

public class Main 
{
    static BigInteger permutations;
    
    static int row;
    static int col;
    static int lastIndexLocationStringS;
    static int firstIndexLocationStringS;
    
    //we will never be sure on suitable rows since it depends on String s and String p
    static String [][]store = new String[1000][5];
    
    static StringJoiner [][] subsequences = new StringJoiner[1000][6];
    
    
    static int minimumWindow;
    static int maximumWindow;
    
    public static void main(String[] args) 
    {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        
        Map <Character, Integer> mp = new HashMap<Character, Integer>();
        
        //AS PER THE CHALLENGE**********
        //String p = "abc";
        //String s = "adobecodebanc";
        
        //TEST CASE 1: findPermutations("cbaebabacd","abc");
        //String p="abc";
        //String s="cbaebabacd";
        
        //TEST CASE 2:  findPermutations("abab","ab");
        //String p = "ab";
        //String s = "abab";
        
        //TEST CASE 3: findPermutations("azazazazazazzzzaaazazazaz", "az")
        //String p = "az";
        //String s = "azazazazazazzzzaaazazazaz";
        
        //TEST CASE 4: findPermutations("azazazazazazzzzaaazazazpp", "az");
        //String p = "az";
        //String s = "azazazazazazzzzaaazazazpp";
        
        //SHOWS CODE PASSING
        //TEST CASE 5: findPermutations("abcbcacab", "abc");
        //String p = "abcc";
        //String s = "abcde";
        
        //PASS
        //String p = "abccddd";
        //String s = "cabccdde";
        
        //String p = "aaaabccc";
        //String s = "abcdefgaaa";
        
        //FAIL
        //String p = "aaaabccc";
        //String s = "abcdefgaaa";
        
        //FAIL
        //String p = "aaabb";
        //String s = "abcdef";
        
        //String p = "a";
        //String s = "a";
	
	    //String p = "abcc";
 	    //String s = "abccab";        
        
      //String p="a"; String s="a";
        
        //String s  = "abcdabead";
        //String p="abd";
        
        //String s  = "amcdaibaxf";
        //String p="abdho";
        
        //String p = "aabbb";
        //String s = "abcdef";
        
        //String s  = "abcdabead";
        //String p="abd";
        
        
        //*********chatGPT test cases
        //String p="a"; String s="a";
        //String p="ab";  String s="ab";
        //String p="ab"; String s="ba";
        //String p="abc";  String s="zabc";
        //String p="aab";  String s="aaab";
        //String p="ab"; String s="cccc";
        //String p="aab";  String s="aaaaa";
        //String p="ab";  String s="zzzacb";
        
        String p="bab";  String s="bcab";
        
        
        //E1 â€” template longer than main (you already handle)
        //String p="abcd";  String s="abc";
        
        //E2 â€” exact fit at end of s (tests your <= gate)
        //String p="abc"; String s="zabc";

        //E3 â€” single char (used to freeze; now must always pass)
        //String p="a"; String s="a";

        //E4 â€” none of pâ€™s letters exist in s (tests your â€œNO CHARACTERSâ€¦â€ path)
        //String p="ab"; String s="ccccccc";

        //E5 â€” letters exist but order makes it impossible
        //String p="abc"; String s="cba";

        //E6 â€” missing one required letter (forces incomplete + â€œinsufficientâ€ near end)
        //String p="aab"; String s="aaaaa";

        //E7 â€” repeats with both min and max windows (your best correctness test)
        //String p="aab"; String s="aaab";

        //E8 â€” repeats where match only exists in one tight location
        //String p="aaab"; String s="baaa";

        //E9 â€” repeats + sparse s (forces fragmented window)
        //String p="aaab"; String s="axaxaxb";

        //E10 â€” match begins late (ensures counter/startPos loop doesnâ€™t skip last viable)
        //String p="ab"; String s="zzzzab";

        //E11 â€” match requires skipping early chars (fragmented subsequence)
        //String p="abc"; String s="abbbc"; // window size 5 for "abc"

        //B) Characters exist but order prevents most permutations
        //String p="abc"; String s="acb";

        //C) Lots of repeats (tests repetition math + matching)
        //String p="aaab"; String s="aaaaab";

        //TC-C1 (produces both MINIMUM and MAXIMUM windows)
        //String p="aab"; String s="aaab";

        //TC-C2 (many windows, duplicates)
        //String p="ab";  String s="abababab";

        //TC-D1 (many identical substring results)
        //String p="ab";  String s="abxxab";

        //TC-B2
        //String p="abc"; String s="abc";

        //TC-B1 (contiguous exact window, but startPos aligns)
        //String p="ab";  String s="ab";

        //TC-A2 (still same bug)
        //String p="a";  String s="ba";

        //1) Single-character p (your confirmed failure)
        //TC-A1
        //String p="a";  String s="a";

        //Test Case 2 â€” two letters, lots of hits
        //String p = "ab";  String s = "abab";

        //Test Case 3 â€” shows fragmented subsequence (not contiguous)
        //String p = "abc";  String s = "axxxbxxc";

        //Test Case 4 â€” early exit (template longer than main)
        //String p = "abcd";  String s = "abc";

        //Test Case 5 â€” repeats in p (this is the best â€œmin vs maxâ€ demonstrator)
        //String p = "aab";  String s = "aaab";

        //Test Case 6 â€” no permutation matches at all
        //String p = "ab"; String s = "cccccc";
        
        int originalNumber=p.length();
        
        int n;
        int r = p.length();
        
        minimumWindow=s.length();
        
        maximumWindow=0;
        
        Map <Integer, BigInteger> m = new HashMap<>();
        
        Permutation perm = new Permutation();
        n=originalNumber;
        
        System.out.println("This is String(s): " + s);
        System.out.println("This is String(p): " + p);
        
        perm.Permutations (n,r,originalNumber, m);
        
        permutations = perm.getPermutations(p);
        System.out.println(permutations);
        
        perm.getPermutationsWithRepetitions(p,mp);
       
        if (perm.hasRepeatRvalues())
        {
            perm.getPermutationsWithRepetitionsCalculator(permutations,p);
            permutations = perm.getFinalPermutationsRepetitions();
            System.out.println("= " + permutations);
        }
       
        //Method call
        System.out.println("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^FINDING PERMUTATION IN STRING S");
        findPermutations(s,p);
    }
    
    public static void findPermutations(String s, String p)
    {
        boolean hasFirstMatch;
        
        String output=null;
        String outputBackup=null;
        
        String outputMinimum=null;
        String outputMinimumBackup=null;
        
        String outputMaximum=null;
        String outputMaximumBackup=null;
        
        String maxOrMin="";
        
        boolean hasSufficientCharactersStringS=true;
        boolean hasIncompleteLettersInStringS=false;
        Set <Integer> stRandomNums = new HashSet<>();
        int pos=0;
        int subsetNumber=1;
        Set <String> st = new HashSet<>();
        StringBuilder sb = new StringBuilder(p);
        int startPos=0;
        boolean hasCharFound=false;
        int counter=0;
        StringJoiner sj;
        int temp1;
        Random rand = new Random();
        String[] valuesSet; 
        String []backupValuesSetBeforeModification;
        int num;
        int count=0;
        int subsetEntry=1;
        int cycles=0;
        int totalcycles=0;
        
        BigInteger difference= new BigInteger("0");
        
        List <String> backupValuesSet = new ArrayList<>();
        int currentSetSize;
        BigInteger newSetSize = new BigInteger("0");
        int n;
        
        //System.out.println("String (s) to search in: " + s);
        //System.out.println("String (p) template word: " + p);
        hasSufficientCharactersStringS=true;
        
        //For subsequence, this is no longer relevant.
        //since we can trim characters from String p as part of subsequence
        //if (s.length()<p.length())
        //{
        //    System.out.println("template word is longer length than main String");
        //    System.exit(0);
        //}
        
        System.out.println("*************INITIAL VALUE OF  CYCLES: " + cycles);
        
        do
        {
            sj=new StringJoiner("");
            
            for (int m=0;m<p.length();m++)
            {
                temp1 = rand.nextInt(p.length());
                currentSetSize=stRandomNums.size();
                stRandomNums.add(temp1);
                
                if (m==0)
                {
                    sj.add(Character.toString(p.charAt(temp1)));
                }
                else
                {
                    if (stRandomNums.size()==currentSetSize)
                    {
                        //System.out.println("repeat random number: " + temp1);
                        m=m-1;
                    }
                    else
                    {
                        //System.out.println("random num: " + temp1);
                        sj.add(Character.toString(p.charAt(temp1)));
                    }
                }
            }
            
            stRandomNums.clear();
            currentSetSize=st.size();
            
            st.add(sj.toString());
            
	        newSetSize = new BigInteger(String.valueOf(st.size()));
	        
	        //THIS IS NEW CODE, IT CAN BE USED BY END USER TO GET ACCOUNTABILITY OF THE SET SIZE AT CERTAIN INTERVALS.
            //NOTE IT WILL HAVE HIT ON THE PERFORMANCE

            if (newSetSize.mod(new BigInteger("200000")).compareTo(new BigInteger("0"))==0) 
            //&& */newSetSize.compareTo(new BigInteger("999"))==1)
            {
                System.out.println("Attempting to add: " + sj +  " into the set (MAX permutations: " + permutations 
                + "\t(CURRENT: " + currentSetSize + "   NEW SIZE: " + newSetSize+"  CYCLES: " + cycles+ ")");
            }
            
            sj=new StringJoiner("");
                
            cycles++;
            totalcycles++;
        
        }while(newSetSize.compareTo(permutations)==-1);

        valuesSet = st.toArray(new String[st.size()]);
        backupValuesSetBeforeModification = st.toArray(new String[st.size()]);
        
        System.out.println("******************Contents of the backup set");
        System.out.println("******************Contents of the valuesSet");
        
        for (String g: valuesSet)
        {
            //System.out.println("Subset " + subsetNumber+": " + g);
            subsetNumber++;
        }
        subsetNumber=1;

        System.out.println("*************NEW VALUE CYCLES: " + cycles);
        System.out.println("*************RUNNING TOTAL CYCLES: " + totalcycles);
        
        System.out.println("***PROCESSING SET AT INDEX: " + (difference));
        System.out.println("**ENDING AT INDEX:***** " + st.size() +"\n");
        
        backupValuesSet= new ArrayList<>(Arrays.asList(backupValuesSetBeforeModification)); 
        
        for (int entry=0; entry<valuesSet.length; entry++)
        {
            if (valuesSet[entry]!="ALREADY PROCESSED")
            {
                //System.out.println("\n\n"+valuesSet[entry] + "\t\tSubset: " + subsetEntry  + "  at cycle number: " + totalcycles);
                //System.out.println("String s: " + s);
                subsetEntry++;
            
                sb=new StringBuilder(valuesSet[entry]);
                
                //System.out.println("String (s) to search in: " + s);
                //System.out.println("String (p) template permutation word: " + sb);
                
                hasSufficientCharactersStringS=true;
                
                
                
                //System.out.println("THIS IS ROW: " + row);
                hasFirstMatch=false;
                
                //do
                //{
                    do
                    {
                        //System.out.println("----------------------------CHECKING BEFORE OVERWRITING: " + subsequences[row][3]);
                
                subsequences[row][0]=new StringJoiner("\t\t");
                subsequences[row][1]=new StringJoiner("\t\t");
                subsequences[row][2]=new StringJoiner("");
                subsequences[row][3]=new StringJoiner("");
                subsequences[row][4]=new StringJoiner("");
                subsequences[row][5]=new StringJoiner("\t\t");
                
                int lengthSubsequence=0;
                        
                        startPos=counter;
                        System.out.println("\nTHIS IS PERMUTATION (STRING Y): " + sb +"\t" + "THIS IS STRING X:  " + s.substring(startPos,s.length()));
                        System.out.println("Subsequence analysis row: " + row);
                         //if (hasSufficientCharactersStringS)
                         //{
                        
                            for (int i=startPos; i<s.length();i++)
                            {
                                //if(sb.toString().length()>(s.length()-i))
				                //{
				                    //System.out.println("Insufficient characters in String s");
				                    //System.out.println("FOLLOWING LETTERS NOT MATCHED: " + sb);
				                    
				                    //hasSufficientCharactersStringS = false;
                                    //sb.delete(0,sb.length());
                                //}
                            
                                if (!sb.toString().isEmpty())
                                {
                                    System.out.println("Checking character: " + sb.toString().charAt(pos) + 
                                    "  against String X index: " + i + "("+s.charAt(i)+")");
                                
                                    //System.out.println("SUBSTRING EXAMINED: " + s.substring(startPos,s.length()));
				                        
				                    //if (hasSufficientCharactersStringS)
				                    //{
				                        if (Character.toString(s.charAt(i)).indexOf(sb.toString().charAt(pos))==0)
				                        {
				                            System.out.println("char found: " + sb.toString().charAt(pos) + "    at String X index: " + i);
				                            System.out.println("char found: " + sb.toString().charAt(pos) + "    at String Y index: " + (p.length()-sb.length()));
				                            lastIndexLocationStringS=i;
	                                        
	                                        hasFirstMatch=true;
	                                        
				                            subsequences[row][0].add(Character.toString(s.charAt(i))+ " index("+i+")");
				                            
				                            //This will be the actual subsequence
				                            subsequences[row][4].add(String.valueOf(sb.toString().charAt(pos)));
				                            subsequences[row][5].add(String.valueOf(sb.toString().charAt(pos))+ " index: ("+ String.valueOf((p.length()-sb.length())+")"));
				                            
				                            lengthSubsequence++;
				                            
				                            //This will allow the entire window to be stored
				                            subsequences[row][2].add(Character.toString(s.charAt(i)));
				                            
				                            //System.out.println("Index String p: " + (p.length()-sb.length()));
				                        
				                            System.out.println(sb.toString().charAt(pos) + " has been removed from StringBuilder (String p)" +  "= "+ sb.toString());
                                            sb.deleteCharAt(pos);
                                            System.out.println("This is current StringBuilder (String p): " + sb.toString());
                                            hasCharFound=true;
                                        
                                            if (sb.length()==p.length()-1)
                                            {
                                                firstIndexLocationStringS=i;
                                            }
                                        }
                                        
                                        else
                                        {
                                            if (hasFirstMatch)
                                            {
                                            System.out.println("char NOT found: " + sb.toString().charAt(pos) + "    at String X index: " + "("+i+") " + Character.toString(s.charAt(i)));
				                            //System.out.println("char NOT found: " + sb.toString().charAt(pos) + "    at String Y index: " + "("+ (p.length()-sb.length())+") " + Character.toString(s.charAt(i)));
                                            
                                            hasCharFound=false;
                                            
                                            //this will store
                                            
                                            
                                            //System.out.println(Character.toString(s.charAt(i)));
                                            
                                            System.out.println("Adding: " + subsequences[row][1].add(Character.toString(s.charAt(i)) +" index("+i+")" + " as unmatched"));
                                             
                                            //This will allow the entire window to be stored
				                            System.out.println("Adding: " + subsequences[row][2].add(Character.toString(s.charAt(i))) + " as running window");
                                            }
                                                
                                            }
				                    //}
                                
                                    //if (hasSufficientCharactersStringS)
				                    //{
				                        if (!sb.toString().isEmpty() && (i==s.length()-1))
                                        {
                                            if (sb.length()==p.length())
                                            {
                                                if (entry==0)
                                                {
                                                    System.out.println("********NO CHARACTERS FROM PERMUTATION TEMPLATE WORD ARE FOUND IN STRING S********");
                                                }
                                            }
                                            //System.out.println("FOLLOWING LETTERS NOT MATCHED: " + sb);
                                            //System.out.println("StringBuilder being emptied: " + sb.toString());
                                            //sb.delete(0,sb.length());
                                            //hasCharFound=false;
                                    
                                            //hasIncompleteLettersInStringS=true;
                                            break;
                                        }
                                    //}
                                }
                            }  //end of for loop int i
                        //}
                        
                        System.out.println("****NOW STORING subsequence length: " +  lengthSubsequence);
                        
                        //String lengthSubsequenceToString = String.valueOf(lengthSubsequenceToString);
                        
                        subsequences[row][3]=new StringJoiner("\n");
                        subsequences[row][3].add(String.valueOf(lengthSubsequence));
                        
                        
                    //we no longer require this as part of subsequence    
                    //}while(!sb.toString().isEmpty());
        
                    //if (sb.toString().isEmpty() && hasCharFound && !hasIncompleteLettersInStringS && hasSufficientCharactersStringS)
                    //{
                    
                    
                    //This will show that entire window examined contains all of the characters from String p
                    if (sb.toString().isEmpty())
                    {
                    
                        System.out.println("**********************************************************");
                        System.out.println(s.substring(startPos,(lastIndexLocationStringS+1)) 
                        + " is a PERFECT substring containing characters matching permutation: " + valuesSet[entry]  + "\t\t\tIndex("+startPos+")");
                        System.out.println("Following characters unmatched: " + subsequences[row][1]);
                        System.out.println("Length maximum subsequence: " +  subsequences[row][3]);
                        System.out.println("Presented window (String X): " + subsequences[row][2] + " index(" +firstIndexLocationStringS+"-"+lastIndexLocationStringS+")");
                        System.out.println("Subsequence: " + subsequences[row][4]);
                        System.out.println("Subsequence (index on String Y): " + subsequences[row][5]);
                        System.out.println("**********************************************************");
                    }   
                    
                    //we know that window does not contain ALL characters from string p
                    else
                    {
                        System.out.println("**********************************************************");
                        System.out.println(s.substring(startPos) + " is NOT a substring containing characters matching permutation: " + valuesSet[entry] 
                        + "\t\t\tIndex("+counter+")");
                        System.out.println("Following characters unmatched (String X): " + subsequences[row][1]);
                        System.out.println("Length maximum subsequence: " +  subsequences[row][3]);
                        System.out.println("Presented window: " + subsequences[row][2] + " index(" +firstIndexLocationStringS+"-"+lastIndexLocationStringS+")");
                        System.out.println("Subsequence: " + subsequences[row][4]);
                        System.out.println("Subsequence (index on String Y): " + subsequences[row][5]);
                        System.out.println("**********************************************************");
                       
                        
                        //if all chars are found from the first match onwards and StringBuilder is not empty, 
                        //it suggests we need to remove trailing characters to complete subsequence
                        if (hasCharFound && !sb.toString().isEmpty())
                        {
                            System.out.println("Following letters require removal (String Y) to support subsequence: " + sb + " \t\t\tindex ("+(p.length()-sb.length())+" - " + (p.length()-1)+")" 
                            +" (length: " + sb.length()+")");
                            //System.out.println(subsequences[row][3]);
                            //System.out.println(Integer.valueOf(subsequences[row][3].toString()));
                            
                            
                            //There might be instance when we need to adjust lengthSubsequence;
                            
                            //System.out.println("Length subsequence: " + lengthSubsequence + "=> " + (lengthSubsequence-sb.length()));
                            //subsequences[row][3] = new StringJoiner("");
                            //subsequences[row][3].add(String.valueOf(lengthSubsequence-sb.length()));
                            
                            sb.delete(0,sb.length());
                            System.out.println("Length subsequence: " + lengthSubsequence + " => " + (lengthSubsequence-sb.length()));
                        }
                        
                        //if ()
                    }
                        
                        //System.out.println("String p (all characters) found within window ("+ (lastIndexLocationStringS-(firstIndexLocationStringS)+1) + ")"    
                        //+  ": \tString s (index: " + firstIndexLocationStringS+" - " + lastIndexLocationStringS+")");
                        
                        //----CHATGPT----
                        // OFF-BY-ONE FIX:
                        // lastIndex - startPos is a distance, but window length is (lastIndex - startPos + 1).
                        // Without +1, exact-length windows like p="abc", s="abc" and p="a", s="a" are found but never stored.
                        // Also fixes p="aab", s="aaab" so the size-3 window at startPos=1 is stored.
                        //----END CHATGPT----
                        
                        /*
                        if(lastIndexLocationStringS-startPos>=p.length())
                        */
                        //if ((lastIndexLocationStringS - startPos + 1) >= p.length())
                        //{
                            //System.out.println("----STORING WINDOW RESULT (MINIMUM): " +s.substring(startPos,(lastIndexLocationStringS+1)) 
                            //+ " (Index: " + firstIndexLocationStringS + "-" + lastIndexLocationStringS + "  Window: " + (lastIndexLocationStringS-firstIndexLocationStringS+1)+")" + "  String p: " + valuesSet[entry]);
                            
                            //store[row][col]=String.valueOf(firstIndexLocationStringS);
                            //store[row][col+1]=String.valueOf(lastIndexLocationStringS);
                            //store[row][col+2]=valuesSet[entry];
                            //store[row][col+3]="MINIMUM";
                            //row++;
                            
                            //System.out.println("----STORING WINDOW RESULT (MAXIMUM): " +s.substring(startPos,(lastIndexLocationStringS+1)) 
                            //+ " (Index: " + firstIndexLocationStringS + "-" + lastIndexLocationStringS + "  Window: " + (lastIndexLocationStringS-firstIndexLocationStringS+1)+")" + "  String p: " + valuesSet[entry]);
                            
                            store[row][col]=String.valueOf(firstIndexLocationStringS);
                            store[row][col+1]=String.valueOf(lastIndexLocationStringS);
                            
                            //This is getting permutation of String p
                            store[row][col+2]=valuesSet[entry];
                            
                            //store[row][col+3]="MAXIMUM";
                            
                            row++;
                        //}
                    //}
		            //if (sb.toString().isEmpty() && !hasCharFound && hasIncompleteLettersInStringS)
                    //{
                      //  System.out.println("**********************************************************");
                    //    System.out.println(s.substring(startPos) + " is NOT a substring containing characters matching permutation:: " + valuesSet[entry] 
                     //   + "\t\t\tIndex("+counter+")");
                      //  System.out.println("**********************************************************");
                    //}
                    //System.out.println("*****RESTORING BACKUP OF STRINGBUILDER (String p): " + valuesSet[entry]);
                    
                    sb=new StringBuilder(valuesSet[entry]);
                    hasCharFound=false;
                    //hasIncompleteLettersInStringS=false;
                    firstIndexLocationStringS=0;
                    firstIndexLocationStringS=0;
                    hasFirstMatch=false;
                    counter++;
            
                //----CHATGPT----
                // OFF-BY-ONE FIX:
                // Allow startPos where p.length() + startPos == s.length() (exact fit at end).
                // Example: p="abc", s="abc" should allow startPos=0 since 3+0 == 3.
                //----END CHATGPT----
                
                /*
                }while(p.length()+startPos<s.length()  && hasSufficientCharactersStringS);
                */
                //----CHATGPT----
                // OFF-BY-ONE / INFINITE-LOOP FIX (p="a", s="a"):
                // At the end of each iteration you increment 'counter', but the while-condition was still using the *previous* startPos.
                // With s length 1, this causes one extra iteration where startPos becomes 1 and the inner loop can't consume sb,
                // making the do{...}while(!sb.isEmpty()) spin forever.
                // Evaluate the gate using the *next* start position (counter) instead.
                //----END CHATGPT----
                
                /*
                }while(p.length()+startPos<=s.length()  && hasSufficientCharactersStringS);
                */
                
                //System.out.println(i);
                
                
                //Since we are now dealing with excluding letters from String Y (equivalent to String p)
                //This while loop condition should run much closer to the edge for a given permutation....
                //we know counter and startPos are closely related and coincide with starting point on String X (String y)
                
                //perhaps we can just come out when counter<=s.length()
                //this way there is no more resilience
                }while(counter<s.length());
                
                //}while(p.length()+counter<=s.length()  /*&& hasSufficientCharactersStringS*/);
                
                System.out.println("\n\n\nSTEP OUT--------------------");

                counter=0;
                startPos=0;
            }  //already processed valuesSet
        
            
        }
        System.out.println("FINISHED ALL PERMUTATIONS!!!!!!!!");
        System.out.println("NUMBER ROWS DATA: " + row);
        
        //System.out.println(subsequences[10][3]);
        //System.out.println(subsequences[9][3]);
        //System.exit(0);
        //System.out.println("\n\n-----------String s: " + s + "\tString p: " + p + "\tMinimum window: " + minimumWindow + "\tMaximum window: " + maximumWindow);                
        //System.out.println("\n\n------------All Windows: String p in String s");

        
        for (int c=0; c<row; c++)
        {
            System.out.println("\nProcessing row: " + c + " of subsequence data");
            
            firstIndexLocationStringS = Integer.valueOf(store[c][col]);
            lastIndexLocationStringS = Integer.valueOf(store[c][col+1]);
            
            //We know this has the data for all the characters found in String s and String p
            
            
            //subsequences[row][0]  //this would be matched characters 
            //subsequences[row][1]  //this would be unmathced characters
            //subsequences[row][2]  //this would be all  running characters (this is effectively the substring)
            
            
            //We only want to print results here even if all characters in String p match or not
            
            //System.out.println("row: " + row);
            
            if (subsequences[c][0].equals(""))
            {
                System.out.println("No matches String p and String s");
            }
            else
            {
                output = 
            s.substring(firstIndexLocationStringS,(lastIndexLocationStringS+1)) 
            + " index(" +firstIndexLocationStringS+"-"+lastIndexLocationStringS+") is a substring NOT containing characters matching permutation: " 
            + store[c][col+2] + "(Window size: " + (lastIndexLocationStringS-(firstIndexLocationStringS)+1)+")";
            
            
            //System.out.println("REST: " + subsequences[c][2].length());
            //System.out.println("REST2: " + subsequences[c][1].length());
            
            System.out.println("CHECK1: " + outputBackup);
            System.out.println("CHECK2: " + output);
            
            
            try
            {
                if (!outputBackup.equals(output))
                {
                        //maxOrMin=store[c][col+3];
                        System.out.println("\n"+output);
                        System.out.println("Following characters unmatched: " + subsequences[c][1]);
            System.out.println("Length maximum subsequence: " +  subsequences[c][3] + "\t\tsubsequence: " + subsequences[c][0]);
            System.out.println("Presented window (String X): " + subsequences[c][2]);
            System.out.println("Subsequence: " + subsequences[c][4]);
            System.out.println("Subsequence (index on String Y): " + subsequences[c][5]);
                        outputBackup=output;
                    }
            }
            catch (NullPointerException e)
            {
                maxOrMin=store[c][col+3];
                outputBackup=output;
                System.out.println("\n"+output);
                System.out.println("Following characters unmatched: " + subsequences[c][1]);
            System.out.println("Length maximum subsequence: " +  subsequences[c][3] + "\t\tsubsequence: " + subsequences[c][0]);
            System.out.println("Presented window (String X): " + subsequences[c][2]);
            System.out.println("Subsequence: " + subsequences[c][4]);
            System.out.println("Subsequence (index on String Y): " + subsequences[c][5]);
            }
                    
            maxOrMin="";
            
            }
            
            
            
                                    
            //output = 
            //s.substring(firstIndexLocationStringS,(lastIndexLocationStringS+1)) 
            //+ " index(" +firstIndexLocationStringS+"-"+lastIndexLocationStringS+") is a substring containing characters matching permutation: " 
            //+ store[c][col+2] + "("+maxOrMin + "   Window size: " + (lastIndexLocationStringS-(firstIndexLocationStringS)+1)+")";   
                    
            
        }
        
        System.out.println("This is current longest subsequence: " + maximumWindow);
        //System.out.println("This is current maximum window: " + maximumWindow);
          
        for (int c=0; c<row; c++)
        {
            //firstIndexLocationStringS = Integer.valueOf(store[c][col]);
            //lastIndexLocationStringS = Integer.valueOf(store[c][col+1]);
            
            //System.out.println("TEST");
            //System.out.println(subsequences[c][3]);
            //System.out.println(Integer.valueOf(subsequences[c][3].toString()));
            
            if((Integer.valueOf(subsequences[c][3].toString())>=maximumWindow))
            {
                maximumWindow= Integer.valueOf(subsequences[c][3].toString());
            }
            
            //if((lastIndexLocationStringS-firstIndexLocationStringS+1)<=minimumWindow)
            //{
             //   minimumWindow= (lastIndexLocationStringS-(firstIndexLocationStringS)+1);
            //}
        }
        
        //System.out.println("This is final minimum window: " + minimumWindow);
        System.out.println("This is final maximum window: " + maximumWindow);
        
        
        System.out.println("\n\n-----------------LONGEST SUBSEQUENCE (STRING Y IN STRING X)");
                
        for (int c=0; c<row; c++)
        {
            firstIndexLocationStringS = Integer.valueOf(store[c][col]);
            lastIndexLocationStringS = Integer.valueOf(store[c][col+1]);
            
            if ((Integer.valueOf(subsequences[c][3].toString())==maximumWindow))
                /*&&(store[c][col+3])=="MAXIMUM")*/
            {
                outputMaximum = s.substring(firstIndexLocationStringS,(lastIndexLocationStringS+1))
                + " index(" +String.valueOf(firstIndexLocationStringS)+"-"+String.valueOf(lastIndexLocationStringS) +") is a substring(String X) with subsequence permutation (String Y): " + store[c][col+2]  
                +"  Window size: " + String.valueOf(lastIndexLocationStringS-firstIndexLocationStringS+1)+")";
                System.out.println("Following characters unmatched: " + subsequences[c][1]);
                System.out.println("Length maximum subsequence: " +  (subsequences[c][3]));
                System.out.println("Presented window (String X): " + subsequences[c][2]);
                System.out.println("Subsequence: " + subsequences[c][4]);
                System.out.println("Subsequence (index on String Y): " + subsequences[c][5]);
                
                try
                {
                    if (!outputMaximumBackup.equals(outputMaximum))
                    {
                        System.out.println(outputMaximum);
                        outputMaximumBackup=outputMaximum;
                    }
                }
                catch (NullPointerException e)
                {
                    outputMaximumBackup=outputMaximum;
                    System.out.println(outputMaximum);
                }
            }
            
            /*
            if ((lastIndexLocationStringS-firstIndexLocationStringS+1==minimumWindow)
            && (store[c][col+3]=="MINIMUM"))  
            {
                outputMinimum = s.substring(firstIndexLocationStringS,(lastIndexLocationStringS+1)) + " index(" +String.valueOf(firstIndexLocationStringS)+"-"+String.valueOf(lastIndexLocationStringS)+") is a substring containing characters matching permutation: " + store[c][col+2] + "(" +store[c][col+3] +"  Window size: " + String.valueOf(lastIndexLocationStringS-firstIndexLocationStringS+1)+")";
                
                try
                {
                    if (!outputMinimumBackup.equals(outputMinimum))
                    {
                        System.out.println(outputMinimum);
                        outputMinimumBackup=outputMinimum;
                    }
                }
                catch (NullPointerException e)
                {
                    outputMinimumBackup=outputMinimum;
                    System.out.println(outputMinimum);
                }
            }
            */
        }
    }  
}
    
class Permutation
{
    static BigInteger result = new BigInteger("0");
    static BigInteger finalResult = new BigInteger("0");
    static int n;
    static int r;
    static int originalNumber;
    static Map <Integer, BigInteger> factorialResults = new HashMap<Integer, BigInteger>();
    
    static BigInteger runningResult;
    
    static StringJoiner multipleRepeatRVals=new StringJoiner("");
    static boolean hasRepeatRValuesInSample=false;
    
    static BigInteger numberPermutationsWithRepetions;
    
    
    public boolean hasRepeatRvalues()
    {
        return hasRepeatRValuesInSample;
    }
    
    public void getPermutationsWithRepetitionsCalculator(BigInteger permutations, String p)
    {
        System.out.println("\n***PERMUTATIONS*** nPr (without replacement)  WITH REPETITION:\t\t" + "String p: " + p);
        System.out.println("P(n,r) = n! / (nÃ¢Ë†â€™r)!  /  " + multipleRepeatRVals.toString().substring(0,multipleRepeatRVals.length()-2) + "\t\t(MULTIPLICATION of factorial of occurrences of each UNIQUE r value in n)");
        System.out.println("P(" + originalNumber+","+r+") = " + originalNumber+"!" + " / " + "("+originalNumber+"-"+r+")!" + " / " + runningResult);

        numberPermutationsWithRepetions = permutations.divide(runningResult);
    }
    
    public BigInteger getFinalPermutationsRepetitions()
    {
        return numberPermutationsWithRepetions;
    }
    
    public BigInteger getPermutations(String p)
    {
        System.out.println("***PERMUTATIONS*** nPr (without replacement)\t\t" + "String p: " + p);
        System.out.println("P(n,r) = n! / (nÃ¢Ë†â€™r)!");
        System.out.println("P(" + originalNumber+","+r+") = " + originalNumber+"!" + " / " + "("+originalNumber+"-"+r+")!");
        
        return result;
    }
    
    public static void getPermutationsWithRepetitions(String strP, Map <Character, Integer> mp)
    {
        char key=' ';
        int val=0;
        int key1;
        
        //long val1;
        BigInteger val1;
        
        long result=0;
        
        for (Character ch: strP.toCharArray())
        {
            if (mp.containsKey(ch))
            {
                int value = mp.get(ch);
                mp.put(ch,(value+1));
            }
            else 
            {
                mp.put(ch,1);
            }
        }
        
        for (Map.Entry<Character, Integer> entry : mp.entrySet()) 
        {
            key = entry.getKey();
            val = entry.getValue();
            
            calculatePermutationsWithRepetitions(key,val);
        }
        
        System.out.println("\n****FACTORIAL INFO:*********");
        for (Map.Entry<Integer, BigInteger> entry : factorialResults.entrySet()) 
        {
            key1 = entry.getKey();
            val1 = entry.getValue();
            
            System.out.println("key: " + key1 + " value: " + val1);
        }
    }
    
    public static BigInteger calculatePermutationsWithRepetitions(char key, int val)
    {
        if (val>1)
        {
            hasRepeatRValuesInSample=true;
            System.out.println("checking the factorial results to ascertain if: " + val + " is present");
            
        if (factorialResults.containsKey(val))
        {
            System.out.println("----------------------------------------------------------------");
            
            result = new BigInteger(String.valueOf(factorialResults.get(val)));
            
            System.out.println("It will perform: " + val+"!" + "=" + result +  "\t due to " +  val + "\toccurrences of: " + key);
            
            try
            {
                
                runningResult = result.multiply(runningResult);
                multipleRepeatRVals.add(val+"!" + " x ");
            }
            catch(NullPointerException e)
            {
                System.out.println("CATCH!!!!!!!!!!!!!!: " + result);
                
                runningResult=new BigInteger(String.valueOf(1));
                
                runningResult = result.multiply(runningResult);
            
                multipleRepeatRVals.add(val+"!" + " x ");
            }
        }
        System.out.println(val+"!  =  " + result);
        
        System.out.println("This is: " + multipleRepeatRVals);
        System.out.println("RUNNING TOTAL (REPETITIONS): " + runningResult + "\t\t" + multipleRepeatRVals.toString().substring(0,(multipleRepeatRVals.length()-2)));
        }
        
        return result;
    }
    
    public static BigInteger Permutations (int n, int r, int originalNumber, Map <Integer, BigInteger> factorialResults)
     {
        Permutation.n=n;
        Permutation.r=r;
	    Permutation.originalNumber=originalNumber;
	    Permutation.factorialResults=factorialResults;
       
        BigInteger temp;
        
        int denominator;
        
        if (originalNumber<r || r<0)
        {
            System.out.println("please enter n Ã¢â€°Â¥ r Ã¢â€°Â¥ 0");
            System.exit(0);
            
            return new BigInteger("0");
        }
        if (n>=1)
        {
            BigInteger setN = new BigInteger(String.valueOf(n));
            BigInteger permFunction = new BigInteger(String.valueOf(Permutations((n-1), r,originalNumber, factorialResults)));
            
            result = new BigInteger(String.valueOf(setN.multiply(permFunction)));
            
            factorialResults.put(n,result);
            
            if (n==originalNumber)
            {
                denominator = originalNumber-r;
                
                if (factorialResults.containsKey(denominator))
                {
                    BigInteger getResult = new BigInteger (String.valueOf(factorialResults.get(denominator)));
                    
                    finalResult=result.divide(getResult);
                    result=finalResult;
                    return result;
                }
            }
            return result;
        }
        
        return new BigInteger("1");
    }
}