题目链接

Problem Statement

As you are probably aware, the Internet protocols specify a canonical byte order convention for data transmitted over the network called network byte order, so that machines with different byte order conventions can communicate. But what if such canonical byte order didn't exist? We would probably be trapped in chaos trying to figure out the byte order for every machine we want to communicate with. But luckily, no matter the byte order (big-endian or little-endian), there will be byte blocks that will always be read correctly.

Imagine you have a list of N byte blocks. In order to minimize the number of trasmission operations required to send all of them, you want to pair as many as possible blocks. Note that the resulting byte frame should have same representation in both network orders, i.e., they should be a palindrome when paired. The rules for such pairings are the following:

  • No block can be paired with itself.
  • A block can be paired zero or one time.
  • You cannot pair more than two blocks.

For the ease of representation we will use lowercase latin characters to represent byte blocks. Suppose we have two blocks [′a′,′a′,′f′] and [′f′], and they are paired to form the frame [′f′,′a′,′a′,′f′], then it has the same representation in any of the byte order.

Now, given the list of blocks, using the pairings described above, what's the minimum number of transmissions required to send them all?

Note: A block can either be transmitted alone, or paired with another block (if the pair satisfies above criteria).

Input Format

There will be multiple test cases per input file. Every test case will start with a number Ntelling you the size of the list. Then N lines follow, each one with a block, where each byte has been replaced by its current English alphabet lowercase letter. No test case will have more than 3000 potential pairs.

Output Format

Output a single line per test case in the input with the required answer.

Constraints

  • 1≤number of test cases≤6
  • 1≤N≤1000
  • 1≤length of each block≤1000
  • Each block consisits of lowercase latin characters, [′a′,′z′].

Sample Input

6
aaababa
aa
ababaaa
baaa
a
b
9
aabbaabb
bbaabbaa
aa
bb
a
bbaa
bba
bab
ab

Sample Output

3
5

Explanation

  • Sample Case #00: All of the blocks can be paired into following 3 frames.

    • "baaa" + "b" = "baaab"
    • "aaababa + "ababaaa" = "aaababaababaaa"
    • "aa" + "a" = "aaa"
  • Sample Case #01: Following frames will be sent

    • "aabbaabb" + "bbaabbaa" = "aabbaabbbbaabbaa"
    • "aa" + "a = "aaa"
    • "bba" + "bb" = "bbabb"
    • "bab" + "ab" = "babab"
    • "bbaa"

又一个之前没有用过的字符串hash的应用。还加了个一般图最大匹配的模板。

AC代码:

  1 #include<set>
  2 #include<map>
  3 #include<cmath>
  4 #include<queue>
  5 #include<cstdio>
  6 #include<vector>
  7 #include<string>
  8 #include<cstdlib>
  9 #include<cstring>
 10 #include<iostream>
 11 #include<algorithm>
 12 using namespace std;
 13
 14 #define mem(a, b) (memset(a, b, sizeof(a)))
 15 #define pb push_back
 16 #define all(v) v.begin(), v.end()
 17 #define rall(v) v.rbegin(), v.rend()
 18 #define rep(i, m) for (int i = 0; i < (int)(m); i++)
 19 #define rep2(i, n, m) for (int i = n; i < (int)(m); i++)
 20 typedef long long LL;
 21 typedef pair<LL, LL> PLL;
 22
 23 const int oo = (int) 1e9;
 24 const double PI = 2 * acos(0);
 25 const double eps = 1e-9;
 26 const int MAX_N = 2048;
 27
 28 const int P = 131;
 29 const int Q = 191;
 30 const int MP = 1000003;
 31 const int MQ = 10000019;
 32 LL pw[MAX_N], qw[MAX_N];
 33 char str[MAX_N];
 34 #define F first
 35 #define S second
 36
 37 /* 采用两个hash函数*/
 38 struct strHash {
 39     PLL str, rev;
 40     int len;
 41
 42     strHash operator +(const strHash &o) const {
 43         strHash res;
 44         res.str.F = (str.F * pw[o.len] + o.str.F) % MP;
 45         res.str.S = (str.S * qw[o.len] + o.str.S) % MQ;
 46         res.rev.F = (o.rev.F * pw[len] + rev.F) % MP;
 47         res.rev.S = (o.rev.S * qw[len] + rev.S) % MQ;
 48         res.len = len + o.len;
 49         return res;
 50     }
 51 }s[MAX_N];
 52
 53 void init() {
 54     pw[0] = qw[0] = 1;
 55     for (int i = 1; i < MAX_N; i++) {
 56         pw[i] = pw[i-1] * P % MP;
 57         qw[i] = qw[i-1] * Q % MQ;
 58     }
 59 }
 60
 61 strHash makeHash(const char *str) {
 62     strHash res;
 63     res.len = strlen(str);
 64     res.str.F = res.str.S = 0;
 65     for (int i = 0; i < res.len; i++) {
 66         res.str.F = (res.str.F * P + str[i]) % MP;
 67         res.str.S = (res.str.S * Q + str[i]) % MQ;
 68     }
 69     res.rev.F = res.rev.S = 0;
 70     for (int i = res.len-1; ~i; i--) {
 71         res.rev.F = (res.rev.F * P + str[i]) % MP;
 72         res.rev.S = (res.rev.S * Q + str[i]) % MQ;
 73     }
 74     return res;
 75 }
 76
 77 /* 判断a+b 或者 b+a是否为回文 */
 78 inline bool check(const strHash &a, const strHash &b) {
 79     strHash u = a + b;
 80     if (u.str == u.rev) return true;
 81     strHash v = b + a;
 82     if (v.str == v.rev) return true;
 83     return false;
 84 }
 85
 86
 87 /* 一般图最大匹配(带花树) */
 88 const int MAX = 2048;
 89 struct GraphMatch {
 90   int Next[MAX];
 91   int spouse[MAX];
 92   int belong[MAX];
 93
 94   int findb(int a) {
 95     return belong[a]==a?a:belong[a]=findb(belong[a]);
 96   }
 97   void together(int a,int b){
 98     a=findb(a),b=findb(b);
 99     if (a!=b)belong[a]=b;
100   }
101
102   vector<int> E[MAX];
103   int N;
104   int Q[MAX],bot;
105   int mark[MAX];
106   int visited[MAX];
107
108   int findLCA(int x,int y){
109     static int t=0;
110     t++;
111     while (1) {
112       if (x!=-1) {
113               x = findb(x);
114               if (visited[x]==t)return x;
115               visited[x]=t;
116               if (spouse[x]!=-1)x=Next[spouse[x]];
117               else x=-1;
118           }
119           swap(x,y);
120       }
121   }
122
123   void goup(int a,int p){
124     while (a!=p){
125           int b=spouse[a],c=Next[b];
126           if (findb(c)!=p)Next[c]=b;
127           if (mark[b]==2)mark[Q[bot++]=b]=1;
128           if (mark[c]==2)mark[Q[bot++]=c]=1;
129           together(a,b);
130           together(b,c);
131           a=c;
132       }
133   }
134
135     void findaugment(int s){
136       for (int i=0;i<N;i++) {
137           Next[i]=-1;
138           belong[i]=i;
139           mark[i]=0;
140           visited[i]=-1;
141       }
142       Q[0]=s;bot=1;mark[s]=1;
143       for (int head=0;spouse[s]==-1 && head<bot;head++){
144           int x=Q[head];
145           for (int i=0;i<(int)E[x].size();i++){
146                 int y=E[x][i];
147                 if (spouse[x]!=y && findb(x)!=findb(y) && mark[y]!=2){
148                     if (mark[y]==1){
149                         int p=findLCA(x,y);
150                         if (findb(x)!=p)Next[x]=y;
151                         if (findb(y)!=p)Next[y]=x;
152                         goup(x,p);
153                         goup(y,p);
154                     }else if (spouse[y]==-1){
155                         Next[y]=x;
156                         for (int j=y;j!=-1;){
157                             int k=Next[j];
158                             int l=spouse[k];
159                             spouse[j]=k;spouse[k]=j;
160                             j=l;
161                         }
162                         break;
163                     }else{
164                         Next[y]=x;
165                         mark[Q[bot++]=spouse[y]]=1;
166                         mark[y]=2;
167                     }
168                 }
169             }
170         }
171     }
172
173     void init(int n) {
174       N = n;
175       for (int i = 0; i < N; ++i) {
176         E[i].clear();
177       }
178     }
179
180     void addEdge(int a, int b) {
181       E[a].push_back(b);
182       E[b].push_back(a);
183     }
184
185     int maxMatch() {
186       int ret = 0;
187       for (int i = 0; i < N; ++i) spouse[i] = -1;
188       for (int i = 0; i < N; ++i) {
189         if (spouse[i] == -1) {
190           findaugment(i);
191         }
192       }
193       for (int i = 0; i < N; ++i) {
194         if (spouse[i] != -1) ++ret;
195       }
196       return ret;
197     }
198 } match;
199
200
201 int main(void) {
202     init();
203     int N;
204     while (~scanf("%d", &N)) {
205         for (int i = 0; i < N; i++) {
206             scanf("%s", str);
207             s[i] = makeHash(str);
208         }
209
210         match.init(N);
211         for (int i = 0; i < N; i++) {
212             for (int j = i+1; j < N; j++) {
213                 if (check(s[i], s[j])) {
214                     match.addEdge(i, j);
215                 }
216             }
217         }
218         int cnt = match.maxMatch();
219         /*
220          for (int i = 0; i < N; i++) {
221              printf("%d %d\n", i, match.spouse[i]);
222          }
223          */
224         printf("%d\n", N - cnt / 2);
225     }
226
227     return 0;
228 }

View Code

转载于:https://www.cnblogs.com/Stomach-ache/p/4425952.html

Joining Byte Blocks(哈希+带花树)相关推荐

  1. luogu P4258 [WC2016]挑战NPC(一般图的最大匹配,带花树,建图、拆点技巧)

    整理的算法模板合集: ACM模板 luogu P4258 [WC2016]挑战NPC 如果是一堆球一堆筐,每一个筐里只能放一个球,求最大能放多少个球, 那么就是一个二分图的最大匹配问题,非常简单,我们 ...

  2. 模板 - 一般图最大匹配(带花树)

    整理的算法模板合集: ACM模板 目录 题目描述 给出一张 n 个点 m 条边的无向图,求该图的最大匹配. 总结一下带花树算法的流程 1.每次找一个未匹配的点出来增广 2.在增广过程中,如果相邻点是白 ...

  3. luogu P6113 【模板】一般图最大匹配(带花树)

    整理的算法模板合集: ACM模板 总结一下带花树算法的流程 1.每次找一个未匹配的点出来增广 2.在增广过程中,如果相邻点是白点,或者是同一朵花中的节点,则直接跳过这个点 3.如果相邻点是一个未被匹配 ...

  4. WC前的颓废——带花树

    QAQ现在很不想写题解博客那就来写个算法吧QAQ... 带花树 题目 来看个题... UOJ79. 某机房里有\(n\)个OIer,其中有\(n\)个男生,\(0\)个女生.现在他们要两两配对. 有\ ...

  5. 【BZOJ4405】【WC2016】挑战NPC(带花树)

    [BZOJ4405][WC2016]挑战NPC(带花树) 题面 BZOJ 洛谷 Uoj Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个 ...

  6. 【学习小记】一般图最大匹配——带花树算法

    Text 一般图的最大匹配仍然是基于寻找增广路的 增广路的定义是这样的一条路径,它不经过重复的点,并且路径两端均没有匹配,且整条路径是非匹配边-匹配边-非匹配边这样交错的. 类比二分图最大匹配的增广路 ...

  7. URAL - 1099 Work Scheduling(一般图最大匹配-带花树模板)

    题目链接:点击查看 题目大意:给出n个警卫,接下来给出数个关系,表示两个警卫可以互相配合,现在规定只有可以互相配合的警卫才能留下来继续工作,问最多能有多少个警卫留下来工作,输出匹配方案 题目分析:一般 ...

  8. 一般图最大匹配——带花树

    所谓花,就是如下图所示的一个奇环: 本文中粗边代表现在的匹配边,细边代表该点的前驱(后文会讲解前驱是什么,现在只需要知道每个点和它的前驱在原图中一定是有边的). 如图所示,一朵包含\(2k+1\)个点 ...

  9. 图论--一般带花树匹配

    带花树就是说一个非二分图,图中带有奇环的图,我们不能在奇环中找增广路,因为会陷入死循环,我们可以将带花树的花(奇环)部分缩成点处理,剩下的图就是一个无奇环的图.我们再找增广路,而奇环中的的点我们可以随 ...

最新文章

  1. url获取网站信息不包含网页源文件内的标签_前嗅ForeSpider链接抽取应用场景及链接在源码的html标签里写脚本...
  2. python面向对象三大特性之继承
  3. python提取图片gps坐标_用python从.docx文件中提取GPS坐标
  4. SuperMap iDesktop 9D中实现地图配准
  5. MongoDB 安装与启动
  6. python从入门到实践第二版_【Python入门教程】第二季网络爬虫基础
  7. innodb_file_per_table参数
  8. nodejs学习笔记-1-文件系统
  9. 场景编辑器 Scene Building
  10. 工作后出国留学经历总结
  11. psn注册什么服务器,怎么注册PSN港服账号?PSN港服官网注册教程
  12. Unity 3d Homework 5 打飞碟游戏实现
  13. 国科大学习资料--人工智能原理与算法-第四次作业解析(学长整理)
  14. 2022年河南省高职单招(综合素质)考试冲刺试题及答案
  15. Excel添加坐标轴单位的方法
  16. 前端上传文件,multipart-formdata,boundary的使用
  17. 彻底删除软件,删除注册列表信息
  18. 快速开发平台:企业信息化建设的不二选择
  19. (课程类 Course)
  20. 字符串输出后面有乱码

热门文章

  1. c# 对象json互相转换_Go语言进阶之路(六):内置JSON库和开源库gjson
  2. 20200507:力扣151周赛下
  3. 文件编码 linux,【原创】Linux基础之文件编码
  4. python编写代码实现文件的拷贝功能_如何使用Python脚本实现文件拷贝
  5. html中使用js、jQuery展示页面小结
  6. layui中列表用文字代表指定数字
  7. SBUS协议转换芯片,SBUS转UART,sbus转rs232,sbus解码IC,zr003
  8. VB根据窗口标题获取应用程序完整路径
  9. 面试指南(二):想跳槽,这些技术点你会了吗?
  10. 最高76%破解成功率!GAN已经能造出“万能指纹”,你的手机还安全吗?