1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define MAXN 15000 5 #define MAXM 510 6 using namespace std; 7 int size, K[5], dp[MAXN][MAXM]; 8 bool vis[MAXN]; 9 char str[MAXM]; 10 struct Trie { 11 int cnt, fail, next[4]; 12 void Init() { 13 cnt = fail = 0; 14 memset(next, 0, sizeof(next)); 15 } 16 }; 17 Trie tree[MAXM]; 18 inline int MAX(int x, int y) { 19 return x > y ? x : y; 20 } 21 inline int GET(char ch) { 22 if (ch == 'A') 23 return 0; 24 if (ch == 'C') 25 return 1; 26 if (ch == 'G') 27 return 2; 28 return 3; 29 } 30 void Insert(char *s) { 31 int now, t; 32 for (now = 0; *s; s++) { 33 t = GET(*s); 34 if (!tree[now].next[t]) { 35 tree[++size].Init(); 36 tree[now].next[t] = size; 37 } 38 now = tree[now].next[t]; 39 } 40 tree[now].cnt++; 41 } 42 void BFS() { 43 int now, i, p; 44 queue<int> q; 45 q.push(0); 46 while (!q.empty()) { 47 now = q.front(); 48 q.pop(); 49 for (i = 0; i < 4; i++) { 50 if (tree[now].next[i]) { 51 p = tree[now].next[i]; 52 q.push(p); 53 if (now) { 54 tree[p].fail = tree[tree[now].fail].next[i]; 55 tree[p].cnt += tree[tree[p].fail].cnt; 56 } 57 } else 58 tree[now].next[i] = tree[tree[now].fail].next[i]; 59 } 60 } 61 } 62 void DoIt() { 63 queue<int> q; 64 int head, temp; 65 int i, j, k, ans, cnt[4]; 66 memset(dp, -1, sizeof(dp)); 67 memset(vis, false, sizeof(vis)); 68 memset(cnt, 0, sizeof(cnt)); 69 for (i = 0; str[i]; i++) 70 cnt[GET(str[i])]++; 71 for (i = 0; i < 5; i++) { 72 if (i) 73 K[i] = K[i - 1] * (cnt[i - 1] + 1); 74 else 75 K[i] = 1; 76 } 77 ans = 0; 78 dp[0][0] = 0; 79 q.push(0); 80 vis[0] = true; 81 while (!q.empty()) { 82 head = q.front(); 83 q.pop(); 84 for (i = 0; i <= size; i++) { 85 if (dp[head][i] < 0) 86 continue; 87 for (j = 0; j < 4; j++) { 88 k = head % K[j + 1] / K[j]; 89 if (k >= cnt[j]) 90 continue; 91 temp = head + K[j]; 92 k = tree[i].next[j]; 93 if (dp[head][i] + tree[k].cnt > dp[temp][k]) { 94 dp[temp][k] = dp[head][i] + tree[k].cnt; 95 ans = MAX(ans, dp[temp][k]); 96 if (!vis[temp]) { 97 vis[temp] = true; 98 q.push(temp); 99 } 100 } 101 } 102 } 103 } 104 printf("%d\n", ans); 105 } 106 int main() { 107 int n, ca = 1; 108 while (scanf("%d", &n), n) { 109 tree[0].Init(); 110 for (size = 0; n--;) { 111 scanf(" %s", str); 112 Insert(str); 113 } 114 scanf(" %s", str); 115 BFS(); 116 printf("Case %d: ", ca++); 117 DoIt(); 118 } 119 return 0; 120 }