标签:int siz 碱基 len np 20113 序列 TJOI2018 nv
[TJOI2018 碱基序列](https://www.luogu.com.cn/problem/P4591)
偷懒直接 SAM 上 DP。
设 dp(i,j) 表示用前 i 行氨基酸匹配到状态 j 的方案数。
由于这个题面比较玄学, 复杂度就挺玄学, 随手加点剪枝就可以很快。
```cpp
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
const int mo = 1e9 + 7;
int siz[20113];
struct node {
int f, len, t[26];
} t[20113];
int a[20113];
int tot = 1, las = 1;
void extnd (int c) {
int np = ++ tot, p = las; las = np;
t[np].len = t[p].len + 1;
for (; p && !t[p].t[c]; p = t[p].f) t[p].t[c] = np;
if (!p) t[np].f = 1;
else {
int v = t[p].t[c];
if (t[v].len == t[p].len + 1) t[np].f = v;
else {
int nv = ++ tot; t[nv] = t[v];
t[nv].len = t[p].len + 1;
for (; p && t[p].t[c] == v; p = t[p].f) t[p].t[c] = nv;
t[np].f = t[v].f = nv;
}
}
siz[np] += 1;
}
int n;
char s[10003];
LL dp[103][20113];
bool cmp (int s1, int s2) { return t[s1].len < t[s2].len; }
int main()
{
scanf ("%d%s", & n, s);
int len = strlen (s);
for (int i = 0; i < len; ++ i) extnd (s[i] - 'A');
dp[0][1] = 1ll;
for (int id = 1; id <= n; ++ id)
{
int k;
scanf ("%d", &k);
for (int i = 0; i < k; ++ i) {
scanf ("%s", s); int sl = strlen (s); if (sl > len) continue;
for (int sta = 1; sta <= tot; ++ sta) if(dp[id - 1][sta]) {
int now = sta;
// tran
for (int j = 0; j < sl; ++ j) { now = t[now].t[s[j] - 'A']; if (!now) break; }
if (now) dp[id][now] += dp[id - 1][sta], dp[id][now] %= mo;
}
}
}
for (int i = 1; i <= tot; ++ i) a[i] = i;
sort (a + 1, a + 1 + tot, cmp);
for (int i = tot; i >= 1; -- i) if (t[a[i]].f) siz[t[a[i]].f] += siz[a[i]];
LL ans = 0ll;
for (int i = 1; i <= tot; ++ i) ans += (LL)dp[n][i] * siz[i] % mo, ans = ans % mo;
cout << ans;
return 0;
}
标签:int,siz,碱基,len,np,20113,序列,TJOI2018,nv 来源: https://www.cnblogs.com/tztqwq/p/14472974.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。