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