Acwing设计密码

题意:

有字符串S,要求:

  • 长度是n
  • 仅包含小写字母
  • 不包含子串T(这里的字串必须是连续才算)

求S的个数

n<=50,|T|<=50;

解法:

分为m+1个状态,从0m,分别表示了当前的S的长度中的next[j]的值

即f[i] [j]表示了在字串长度是i时,最后一个字符所能匹配到的T中最大的下标(就是next的定义)

根据当前字符的取值转移到f[i+1] [x]的状态

复杂度:

n * m * 26 * n

#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
#define LL long long
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 55,mod=1e9+7;
int n, m;
int f[N][N];
int ne[N];
string str;
int main() {
	cin >> n;
	cin >> str;
	m = str.size();
	str = " " + str;
	f[0][0] = 1;
	for (int i = 2, j = 0; i <= m; i++) {
		while (j&&str[i] != str[j + 1])j = ne[j];
		if (str[i] == str[j + 1])j++;
		ne[i] = j;
	}
	for(int i=0;i<n;i++)
		for(int j=0;j<=m;j++)
			for (char z = 'a'; z <= 'z'; z++) {
				int u = j;
				while (u&&str[u + 1] != z)u = ne[u];
				if (str[u + 1] == z)u++;
				if (u != m)f[i + 1][u] = (f[i + 1][u] + f[i][j]) % mod;
			}
	int res = 0;
	for (int i = 0; i < m; i++)res = (res + f[n][i]) % mod;
	cout << res << endl;

}