#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> using namespace std; const int maxn=1024+10, DEF=0x8f8f8f8f; int n, m, rt, tot, val[maxn]; bool f[2][maxn][maxn]; struct node { int nxt[4], fail, st; void Init() { fail=st=0; memset(nxt, 0, sizeof nxt); return ; } }tr[maxn]; int getch(char c) { if(c=='A') return 0; if(c=='T') return 1; if(c=='G') return 2; return 3; } void Insert(int rt, int k, char *ch) { for(int i=0, len=strlen(ch), cur; i<len; i++) { cur=getch(ch[i]); if(!tr[rt].nxt[cur]) { tr[++tot].Init(); tr[rt].nxt[cur]=tot; } rt=tr[rt].nxt[cur]; } tr[rt].st|=(1<<k); return ; } void Build(int rt) { queue<int> q; q.push(rt); while(!q.empty()) { int now=q.front(), p=0; q.pop(); for(int i=0; i<4; i++) { if(!tr[now].nxt[i]) tr[now].nxt[i]=tr[tr[now].fail].nxt[i]; else { p=tr[now].nxt[i]; q.push(p); if(now) tr[p].fail=tr[tr[now].fail].nxt[i]; tr[p].st|=tr[tr[p].fail].st; } } } return ; } int Cal(int st) { int cnt=0; for(int i=0; i<n; i++) if(st&(1<<i)) cnt+=val[i]; return cnt; } int Work() { memset(f, 0, sizeof f); f[0][0][0]=1; int lim=1<<n, u=0, ans=DEF; for(int i=1; i<=m; i++) { u^=1; memset(f[u], 0, sizeof f[u]); for(int j=0; j<=tot; j++) for(int k=0; k<lim; k++) for(int h=0; h<4; h++) f[u][tr[j].nxt[h]][k|tr[tr[j].nxt[h]].st]|=f[u^1][j][k]; } for(int i=0; i<=tot; i++) for(int j=0; j<lim; j++) if(f[u][i][j]) ans=max(ans, Cal(j)); return ans; } int main() { while(scanf("%d%d", &n, &m)!=EOF) { rt=0, tot=0; tr[rt].Init(); char s[maxn]; for(int i=0; i<n; i++) { scanf("%s%d", s, &val[i]); Insert(rt, i, s); } Build(rt); int ans=Work(); ans<0 ? printf("No Rabbit after 2012!\n") : printf("%d\n", ans); } return 0; }
|