Python solution: modularized DP and KMP for string matching
\nfrom functools import lru_cache\nclass Solution:\n    \n    # To solve this problem, we will use DP, because of the structured nature\n    # we are basically 
```\nfrom functools import lru_cache\nclass Solution:\n    \n    # To solve this problem, we will use DP, because of the structured nature\n    # we are basically searching for each index, the space between s1[:i+1] and s2[:i+1], and exclude all the branches which contains evil as substring\n    # We can quickly conduct string matching between evil and current string by the KMP algorithm\n    \n    # c = character to be matched\n    # j = current pointer position on pattern\n    def kmp_core(self, c, j):\n        while j > 0 and c != self.pattern[j]:\n            j = self.lps[j-1]\n        if c == self.pattern[j]:\n            j += 1\n        return j\n    \n    # self matching to construct the lps array\n    def getKmpNext(self):\n        n, j = len(self.pattern), 0\n        self.lps = [0] * n\n        for i in range(1, n):\n            j = self.kmp_core(self.pattern[i], j)\n            self.lps[i] = j\n            \n    # pre1 and pre2 = whether the current considered word share prefices with s1 and s2 respectively\n    # preE = how many indices I have matched with evil when I build the current string\n    @lru_cache(None)\n    def dp(self, idx, pre1, pre2, preE):\n        # We reached the end of evil. So the current considered substring contains evil, return 0\n        if preE == len(self.pattern):\n            return 0\n        # We reached the end of s1 and s2. Finished as a good string, so return 1\n        if idx == len(self.s1):\n            return 1\n\n        total, first, last = 0, ord(\'a\'), ord(\'z\')\n        if pre1:\n            first = ord(self.s1[idx])\n        if pre2:\n            last = ord(self.s2[idx])\n\n        for ci in range(first, last + 1):\n            _pre1 = pre1 and ci == first\n            _pre2 = pre2 and ci == last\n\n            # conduct one step of KMP to compute how long does the current string matches with evil\n            _preE = self.kmp_core(chr(ci), preE)\n\n            total += self.dp(idx + 1, _pre1, _pre2, _preE)\n            total %= self.MOD            \n        return total\n    \n    def findGoodStrings(self, n: int, s1: str, s2: str, evil: str) -> int:\n        m, self.MOD = len(evil), pow(10,9)+7\n        self.pattern, self.s1, self.s2 = evil, s1, s2\n        self.getKmpNext()\n        return self.dp(0, True, True, 0);\n```
[]