Python | Backtracking, works and easy to understand
python\nfrom functools import lru_cache\nclass Solution:\n    def numPermsDISequence(self, s):\n        return self.backtrack(s) % (10**9 + 7)\n\n    def backtr
```python\nfrom functools import lru_cache\nclass Solution:\n    def numPermsDISequence(self, s):\n        return self.backtrack(s) % (10**9 + 7)\n\n    def backtrack(self, s):  # with pruning and memo\n        L = len(s)\n        nums = set(range(-1, L + 1))  # dummy -1 as \'pre\', only happens when idx == 0 (in which case we don\'t need var \'pre\')\n\n        @lru_cache(None)\n        def backtrack(idx, pre):  # current index\n            nums.remove(pre)\n\n            cnt = 0\n            if not nums:            cnt = 1  # empty, it\'s a valid permutation\n            elif idx == 0:          cnt = sum(backtrack(idx + 1, num) for num in range(L + 1))\n            elif s[idx - 1] == \'D\': cnt = sum(backtrack(idx + 1, num) for num in range(pre) if num in nums)\n            elif s[idx - 1] == \'I\': cnt = sum(backtrack(idx + 1, num) for num in range(pre + 1, L + 1) if num in nums)\n\n            nums.add(pre)  # recover\n            return cnt\n\n        return backtrack(0, -1)\n```
['Backtracking', 'Memoization', 'Python']