Python [O(1) space] [Detailed explanation]
We can solve this problem with constant space complexity (unlike the question hints). Let us consider the string abcde, which is of length 5. Consider length-3 
We can solve this problem with constant space complexity (unlike the question hints). Let us consider the string `abcde`, which is of length 5. Consider length-3 combinations. We will use the variable `state` to keep track of the indices used for combination. So at first step we have `abc`, which is `[0,1,2]`. The last step will be `cde`, which is `[2,3,4]`. At every time, we increment the current state by 1 from the end. However, we do so only if the end location is not already maxed out. If it is already maxed out, we decrement the index by 1 and keep looking.\n\nFor example, say the last value we returned is `ade`, which is `[0,3,4]`. \n* We start from the last position, `i=2`. `state[i] = max_state[i] = 4`.\n* We move to `i=1`. Once again `state[i] = max_state[i] = 3`.\n* We move to `i=0`. Here `state[i] < max_state[i]`. So we increment `state[i]` by 1. All states trailing `i` are obtained by sequentially incrementing `state[i]` by 1. This gives the new state as `[1,2,3]` which corresponds to `bcd`, as it should be. If we reach `max_state` we set `next_flag = False` which means there is no next state.\n\nRun complexity: `O(N)` where `N` is the number of calls to functions `next` and `hasNext`.\nSpace complexity: `O(1)`\n\n```\nclass CombinationIterator:\n    def __init__(self, c, l):\n        self.c = c\n        self.state = list(range(l))\n        self.max_state = list(range(len(c)-l, len(c)))\n        self.next_flag = True\n\n        \n    def next(self):\n        ret = \'\'.join([self.c[i] for i in self.state]) #the combination at this time\n        if all((x==y for x,y in zip(self.state, self.max_state))): #max state reached, set next_flag as false\n            self.next_flag = False\n        else: #max state not reached, find the next state\n            i = len(self.state)-1 #start from the end\n            while self.state[i] == self.max_state[i]: #go to the left state if this state is already maxed\n                i -= 1\n            self.state[i] += 1 #increment the available state\n            self.state = self.state[:i+1] + list(range(self.state[i]+1, self.state[i]+len(self.state)-i)) #all the trailing indices are reset in value\n        return ret\n    \n    \n    def hasNext(self):\n        return self.next_flag\n```
[]