码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-05-19 18:46:20      阅读:284      评论:0      收藏:0      [点我收藏+]

标签:using   相关   nbsp   amp   mod   else   sig   void   判断   

题目分析:

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

容易想到一个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] 碱基序列 【哈希】【动态规划】

标签:using   相关   nbsp   amp   mod   else   sig   void   判断   

原文地址:https://www.cnblogs.com/Menhera/p/9060947.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!