题目链接:https://leetcode-cn.com/problems/find-all-good-strings/
一句话思路:
d[i][j]代表以字典序小于等于字符串s[0,i]长度位i的字符串为前缀,并且匹配到evil第j个字符(匹配过程用next数组进行失配转移),满足题意的后缀种类数。
typedef long long ll;
const ll mod = 1e9 + 7;
const int maxn = 500 + 10;
int nxt[maxn];
ll d[maxn][60];
string s,ev;
void get_next(string & ev) {
int n = ev.length();
int j = nxt[0] = -1;
int i = 0;
while(i < n) {
if(j == -1 || ev[i] == ev[j]) {
i++;j++;
nxt[i] = j;
}
else j = nxt[j];
}
}
int dfs(int cur, int u, bool flag) {
if(u >= ev.length()) return 0;
if(cur >= s.length()) return 1;
if(!flag && ~d[cur][u]) return d[cur][u];
int li = 'z';
if(flag) li = s[cur];
int ret = 0;
for(char i = 'a'; i <= li; i++) {
int j = u;
while(j >= 0 && ev[j] != i) j = nxt[j];
if(j == -1 || i == ev[j]) j++;
(ret += dfs(cur + 1, j, flag && (i == li) )) %= mod;
}
if(!flag) d[cur][u] = ret;
return ret;
}
class Solution {
public:
int findGoodStrings(int n, string s1, string s2, string evil) {
get_next(evil);
int ans1, ans2;
ev = evil;
memset(d, -1, sizeof(d));
s = s2;
ans1 = dfs(0, 0, true);
s = s1;
ans2 = dfs(0, 0, true);
//cout << ans1 << " " << ans2 << endl;
int ans = (ans1-ans2+mod) % mod;
if(s1.find(evil) == string::npos) (ans+=1)%=mod;
return ans;
}
};