挺有意思的一道题目,解法是AC自动机+DP。
AC自动机建立fail指针时,一定要注意结点的属性也需要传递。AC自动机结合了trie和kmp的优点。
需要注意的是,每个模式串仅计算一次,否则这题很难解。
1 /* 4057 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <algorithm> 12 #include <cstdio> 13 #include <cmath> 14 #include <ctime> 15 #include <cstring> 16 #include <climits> 17 #include <cctype> 18 #include <cassert> 19 #include <functional> 20 #include <iterator> 21 #include <iomanip> 22 using namespace std; 23 //#pragma comment(linker,"/STACK:102400000,1024000") 24 25 #define sti set<int> 26 #define stpii set<pair<int, int> > 27 #define mpii map<int,int> 28 #define vi vector<int> 29 #define pii pair<int,int> 30 #define vpii vector<pair<int,int> > 31 #define rep(i, a, n) for (int i=a;i<n;++i) 32 #define per(i, a, n) for (int i=n-1;i>=a;--i) 33 #define clr clear 34 #define pb push_back 35 #define mp make_pair 36 #define fir first 37 #define sec second 38 #define all(x) (x).begin(),(x).end() 39 #define SZ(x) ((int)(x).size()) 40 #define lson l, mid, rt<<1 41 #define rson mid+1, r, rt<<1|1 42 43 const int maxn = 15; 44 const int maxm = 1030; 45 const int maxl = 105; 46 char s[maxl]; 47 int W[maxn]; 48 bool dp[2][maxm][maxm]; 49 int n, m, l; 50 51 typedef struct { 52 static const int maxn = 1025; 53 static const int rt = 1; 54 int nxt[maxn][4]; 55 int fail[maxn]; 56 int f[maxn]; 57 int m; 58 59 void init() { 60 m = 1; 61 memset(f, 0, sizeof(f)); 62 memset(nxt, 0, sizeof(nxt)); 63 } 64 65 int newNode() { 66 return ++m; 67 } 68 69 int getId(char c) { 70 if (c == 'A') return 0; 71 if (c == 'T') return 1; 72 if (c == 'G') return 2; 73 if (c == 'C') return 3; 74 return -1; 75 } 76 77 void Insert(char *s, int k) { 78 int i = 0, id; 79 int p = 1, q; 80 81 while (s[i]) { 82 id = getId(s[i]); 83 q = nxt[p][id]; 84 if (!q) 85 q = nxt[p][id] = newNode(); 86 p = q; 87 ++i; 88 } 89 f[p] |= (1 << k); 90 } 91 92 void Build() { 93 int cur; 94 queue<int> Q; 95 96 fail[rt] = rt; 97 rep(i, 0, 4) { 98 if (nxt[rt][i] == 0) { 99 nxt[rt][i] = rt; 100 } else { 101 fail[nxt[rt][i]] = rt; 102 Q.push(nxt[rt][i]); 103 } 104 } 105 106 while (!Q.empty()) { 107 cur = Q.front(); 108 Q.pop(); 109 rep(i, 0, 4) { 110 if (nxt[cur][i] == 0) { 111 nxt[cur][i] = nxt[fail[cur]][i]; 112 } else { 113 fail[nxt[cur][i]] = nxt[fail[cur]][i]; 114 f[nxt[cur][i]] |= f[nxt[fail[cur]][i]]; 115 Q.push(nxt[cur][i]); 116 } 117 } 118 } 119 } 120 121 } AC; 122 123 AC ac; 124 125 int calw(int x) { 126 int ret = 0; 127 128 rep(i, 0, n) { 129 if (x & (1<<i)) 130 ret += W[i]; 131 } 132 133 return ret; 134 } 135 136 void solve() { 137 int ans = INT_MIN; 138 int mst = 1<<n, nst, nxt; 139 int p = 0, q = 1; 140 141 m = ac.m; 142 memset(dp, 0, sizeof(dp)); 143 dp[0][ac.rt][0] = true; 144 rep(i, 1, l+1) { 145 memset(dp[q], 0, sizeof(dp[q])); 146 rep(j, 1, m+1) { 147 rep(k, 0, 4) { 148 rep(st, 0, mst) { 149 if (dp[p][j][st]) { 150 nxt = ac.nxt[j][k]; 151 nst = st | ac.f[nxt]; 152 dp[q][nxt][nst] = true; 153 } 154 } 155 } 156 } 157 p = q; 158 q ^= 1; 159 } 160 161 rep(st, 0, mst) { 162 rep(j, 1, m+1) { 163 if (dp[p][j][st]) { 164 ans = max(ans, calw(st)); 165 break; 166 } 167 } 168 } 169 170 if (ans < 0) 171 puts("No Rabbit after 2012!"); 172 else 173 printf("%d ", ans); 174 } 175 176 int main() { 177 ios::sync_with_stdio(false); 178 #ifndef ONLINE_JUDGE 179 freopen("data.in", "r", stdin); 180 freopen("data.out", "w", stdout); 181 #endif 182 183 int len, w; 184 185 while (scanf("%d %d",&n,&l) != EOF) { 186 ac.init(); 187 rep(i, 0, n) { 188 scanf("%s %d", s, &W[i]); 189 ac.Insert(s, i); 190 } 191 192 ac.Build(); 193 solve(); 194 } 195 196 #ifndef ONLINE_JUDGE 197 printf("time = %d. ", (int)clock()); 198 #endif 199 200 return 0; 201 }