大致题意:
给定一个数
与一个字符串
问有多少个长度为
的字符串包含
对
取模
实际上不是特别难啊….但是谷歌翻译又一次
了我
我以为是包含一个子序列 可以不连续,磕不出来
连续子串就好做了
表示已经放了
个左右括号,未匹配的左括号有
个,当前字符串有长度为
的后缀与
的前缀匹配,
表示是否以及出现过连续字串
我们预处理出来
表示以及有
位与
从头匹配,加一个”
”或”
”之后能匹配的长度
能转移到
和
答案就是
#include <bits/stdc++.h>
using namespace std;
const int N = 203;
const int MOD = 1e9 + 7;
int n, ssz;
string s;
int len[N][2];
int dp[N][N][N][2];
int calc(const string &t) {
int tsz = t.size();
for (int i = tsz; i > 0; --i) {
if (s.substr(0, i) == t.substr(tsz - i, i))
return i;
}
return 0;
}
void add(int &a, int b) {
a += b;
if (a >= MOD)
a -= MOD;
if (a < 0)
a += MOD;
}
int main() {
#ifdef _DEBUG
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
cin >> n >> s;
ssz = s.size();
if (s[0] == '(')
len[0][0] = 1;
else
len[0][1] = 1;
string pref;
int t = 0;
for (int i = 0; i < ssz; ++i) {
pref[++t] = s[i];
pref[++t] = '(';
len[i + 1][0] = calc(pref);
t--;
pref[++t] = ')';
len[i + 1][1] = calc(pref);
t--;
}
dp[0][0][0][0] = 1;
for (int i = 0; i < 2 * n; ++i) {
for (int j = 0; j <= n; ++j) {
for (int pos = 0; pos <= ssz; ++pos) {
for (int f = 0; f < 2; ++f) {
if (dp[i][j][pos][f] == 0) continue;
if (j + 1 <= n)
add(dp[i + 1][j + 1][len[pos][0]][f | (len[pos][0] == ssz)], dp[i][j][pos][f]);
if (j > 0)
add(dp[i + 1][j - 1][len[pos][1]][f | (len[pos][1] == ssz)], dp[i][j][pos][f]);
}
}
}
}
int ans = 0;
for (int i = 0; i <= ssz; ++i)
add(ans, dp[2 * n][0][i][1]);
cout << ans << endl;
return 0;
}