BZOJ5337 [TJOI2018] 碱基序列 哈希动态规划

Posted Menhera

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ5337 [TJOI2018] 碱基序列 哈希动态规划相关的知识,希望对你有一定的参考价值。

题目分析:

这道题的难点在于要取模,而题面没有写。

容易想到一个O(1E7)的dp。KMP或者哈希得到相关位置然后对于相关位置判断上一个位置有多少种情况。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 10200;
 5 
 6 const int mod = 1000000007;
 7 
 8 int n;
 9 string str;
10 string fm[102][12];
11 int num[102];
12 
13 const int Kh = 2;
14 
15 struct hnum{
16     int base;
17     unsigned long long multi[10200];
18     unsigned long long hash[10200];
19 }h[2];
20 
21 void read(){
22     ios::sync_with_stdio(false);
23     cin.tie();
24     cin >> n;
25     cin >> str;
26     for(int i=1;i<=n;i++){
27     cin >> num[i];
28     for(int j=1;j<=num[i];j++) {cin >> fm[i][j];}
29     }
30 }
31 
32 long long rm[2][maxn];
33 int d[maxn];
34 
35 void KMP(int c,int m){
36     memset(d,0,sizeof(d));
37     string &p = fm[c][m];
38     for(int o = 0;o<Kh;o++){
39     unsigned long long now = 0;
40     for(int i=0;i<p.length();i++)
41         now += (p[i]-A+1)*h[o].multi[i];
42     for(int i=p.length()-1;i<str.length();i++){
43         unsigned long long data;
44         if(i!=p.length()-1)data = h[o].hash[i]-h[o].hash[i-p.length()];
45         else data = h[o].hash[i];
46         if(now == data) d[i]++;
47         now = now*h[o].base;
48     }
49     }
50     for(int i=0;i<str.length();i++) if(d[i]==Kh)d[i]=1;else d[i]=0;
51 }
52 
53 void build_hash(){
54     for(int i=0;i<Kh;i++){
55     h[i].multi[0] = 1;
56     for(int j=1;j<str.length();j++){
57         h[i].multi[j] = h[i].multi[j-1]*h[i].base;
58     }
59     h[i].hash[0] = str[0]-A+1;
60     for(int j=1;j<str.length();j++){
61         h[i].hash[j] = h[i].hash[j-1]+(str[j]-A+1)*h[i].multi[j];
62     }
63     }
64 }
65 
66 void work(){
67     h[0].base = 19,h[1].base = 31;
68     build_hash();
69     for(int i=1;i<=num[1];i++){
70     KMP(1,i); for(int k=0;k<str.length();k++) rm[1][k] += d[k];
71     }
72     for(int i=2;i<=n;i++){
73     memset(rm[i&1],0,sizeof(rm[i&1]));
74     for(int j=1;j<=num[i];j++){
75         KMP(i,j); int len = fm[i][j].length();
76         for(int k=0;k<str.length();k++){
77         if(d[k]){
78             if(k-len<0) continue;
79             rm[i&1][k] += rm[(i+1)&1][k-len];
80             rm[i&1][k] %= mod;
81         }
82         }
83     }
84     }
85     long long ans = 0;
86     for(int j=0;j<str.length();j++){
87     ans += rm[n&1][j]; ans %= mod;
88     }
89     printf("%lld",ans);
90 }
91 
92 int main(){
93     read();
94     work();
95     return 0;
96 }

 

以上是关于BZOJ5337 [TJOI2018] 碱基序列 哈希动态规划的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4892][TJOI2017]DNA(后缀数组)

[TJOI2018]碱基序列

[TJOI2018]碱基序列

[TJOI2017]DNA --- 后缀数组

[TJOI2017]DNA

bzoj5336:[TJOI2018]party