题意:给定你n个文本串 ,m个模式串,怎么构造最短的新的文本串使得这个新的文本串包含n个文本串的所有信息且文本串的长度最短且不包含模式串。

解题思路:这里看题解撸的,首先我们算出两两文本串的距离(end数组标记文本和模式串的值不同,利用这个进行bfs算出两两之间的最短距离,注意到这里模式串的end是不能走到的。这里也不需要松弛操作),然后因为n只有10这么大,所以我们可以状态压缩  ,dp[i][j] 表示 压缩后状态为 i(二进制压缩,每i位表示第i个是否在)且 以j结尾的文本串的最小花费。这样去dp即可。

解题代码:

  1 // File Name: temp.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年09月11日 星期四 15时18分4秒
  4 
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #include<queue>
 25 #define LL long long
 26 #define maxn 60002
 27 #define INF  0x3f3f3f3f
 28 using namespace std;
 29 int n,m;
 30 struct Trie
 31 {
 32     int next[maxn][2],fail[maxn],end[maxn];
 33     int root, L;
 34     int newnode()
 35     {
 36         memset(next[L],-1,sizeof(next[L]));
 37         end[L++] = 0 ;
 38         return L-1;
 39     }
 40     void init()
 41     {
 42         L = 0 ; 
 43         root = newnode();
 44     }
 45     void insert(char buf[],int status)
 46     {
 47         int now = root;
 48         int len = strlen(buf);
 49         for(int i = 0 ;i < len ;i ++)
 50         {
 51             if(next[now][buf[i] - '0'] ==  -1)
 52                 next[now][buf[i] - '0'] = newnode();
 53             now = next[now][buf[i] - '0'];
 54         }
 55         end[now] = status;
 56     }
 57     void build()
 58     {
 59         queue<int> Q;
 60         fail[root] = root; 
 61         for(int i = 0;i < 2;i ++)
 62         {
 63             if(next[root][i] == -1)
 64             {
 65                 next[root][i] = root;  //指向root 是没有问题的,我们主要是通过end 数组对个数进行计数的。    
 66             }else{
 67                 fail[next[root][i]] = root;
 68                 Q.push(next[root][i]);
 69             }
 70         }
 71         while(!Q.empty())
 72         {
 73             int now = Q.front();
 74             Q.pop();
 75             for(int i = 0 ;i < 2;i ++)
 76             {
 77                 if(next[now][i] == -1)
 78                 {
 79                     next[now][i] =  next[fail[now]][i]; 
 80                 }
 81                 else{
 82                     fail[next[now][i]] = next[fail[now]][i];
 83                     Q.push(next[now][i]);
 84                 }
 85             }
 86         }
 87     }
 88     int g[11][11];
 89     int dp[1025][11];
 90     int cnt;
 91     int pos[11];
 92     int dis[60010];
 93     void bfs(int k )// bfs  因为是直接 bfs  所以没有松弛操作
 94     {
 95         queue<int> q; 
 96         memset(dis,-1,sizeof(dis));
 97         dis[pos[k]] = 0 ;
 98         q.push(pos[k]);
 99         while(!q.empty())
100         {
101            int now = q.front();
102            q.pop();
103            for(int i = 0 ;i < 2; i ++)
104            {
105               int tmp = next[now][i];
106               if(dis[tmp] < 0 && end[tmp] >= 0 )
107               {
108                   dis[tmp] = dis[now] +1;
109                   q.push(tmp);
110               }
111            }
112         }
113        for(int i = 0 ;i < cnt; i ++)
114            g[k][i] = dis[pos[i]];
115     }
116 int query()
117     {
118 
119         pos[0] = 0;
120         cnt = 1;
121         for(int i = 0;i < L;i++)
122             if(end[i] > 0)
123                 pos[cnt++] = i;
124         for(int i = 0; i < cnt;i++)
125             bfs(i);
126 
127         for(int i = 0;i < (1<<n);i++)
128             for(int j = 0;j < cnt;j++)
129                 dp[i][j] = INF;
130         dp[0][0] = 0; //
131         for(int i = 0;i <(1<<n);i++)
132             for(int j = 0;j < cnt;j++)
133                 if(dp[i][j]<INF)
134                 {
135                     for(int k = 0;k < cnt;k++)
136                     {
137                         if(g[j][k] < 0)continue;
138                         if( j == k)continue;
139                         dp[i|end[pos[k]]][k] = min(dp[i|end[pos[k]]][k],dp[i][j]+g[j][k]);
140                     }
141                 }
142         int ans = INF;
143         for(int j = 0;j < cnt;j++)
144             ans = min(ans,dp[(1<<n)-1][j]);
145         return ans;
146     }
147 };
148 Trie ac;
149 char str[50005];
150 int main(){
151     while(scanf("%d %d",&n,&m ) != EOF)
152     {
153      if(n == 0 && m == 0 )
154          break;
155       ac.init();
156       for(int i = 0;i < n;i ++)
157       {
158         scanf("%s",str);
159         ac.insert(str,1<<i);
160       }
161       for(int i = 1;i <= m;i ++)
162       {
163          scanf("%s",str);
164          ac.insert(str,-1);
165       }
166       ac.build();
167       
168       printf("%d\n",ac.query());
169     }
170     return 0;
171 }
View Code

 

posted on 2014-09-16 19:27  dark_dream  阅读(197)  评论(0编辑  收藏  举报