First, this declaration:
long long n
cin>>n;//takes size of string//
char s[n];
Is non-standard. g++ supports it, but I don't believe variable sized arrays have made it into the C++ standard as it has for C. And I doubt you need long long
as your index type unless you are scaling beyond 2 billion items.
Better:
int n;
cin>>n; //takes size of string
vector<char> s(n);
s
is effectively the same as an array as for as accessing it at index locations with the []
operation.
Back to the solution:
Use a hash table that maps between a character and the number of occurrences of that character as you scan the s
array once. Then use another array to keep track of how many times the character at that index was seen up to that point.
std::vector<int> positionCount(n);
std::unordered_map<char, int> table;
Insert your characters from s
into the table and positionCount table as follows
for (int i = 0; i < n; i++)
{
char c = s[i];
// table[c] is the number of occurrences that "c" was seen in the input array so far
table[c]++;
// since table[c] is getting updated as we iterate,
// Keep track of the count of the char at position i in a separate array
positionCount[i] = table[c];
};
Then for each test case:
for(i=0;i<p;i++)
{
cin>>q; //takes index to check till
q--; // off by 1 fix since the array is described as 1..N
long result = positionCount[q];
result--; // off by 1 fix again since the output is the preceeding count and doesn't include the character at position q.
cout << result << endl;
}
All of the above is intuitively faster since there's no inner for loop. Hash table insertion and lookup is O(1) as is each array lookup.
And if you are into the whole brevity thing, you can simplify the above into this:
for (int i = 0; i < n; i++)
{
positionTable[i] = table[s[i]]++;
}
for(i=0;i<p;i++)
{
cin >> q;
cout << positionTable[q-1] << endl;
}