Joining Byte Blocks(哈希+带花树)
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代码:
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; #define mem(a, b) (memset(a, b, sizeof(a)))
#define pb push_back
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i, m) for (int i = 0; i < (int)(m); i++)
#define rep2(i, n, m) for (int i = n; i < (int)(m); i++)
typedef long long LL;
typedef pair<LL, LL> PLL; const int oo = (int) 1e9;
const double PI = * acos();
const double eps = 1e-;
const int MAX_N = ; const int P = ;
const int Q = ;
const int MP = ;
const int MQ = ;
LL pw[MAX_N], qw[MAX_N];
char str[MAX_N];
#define F first
#define S second /* 采用两个hash函数*/
struct strHash {
PLL str, rev;
int len; strHash operator +(const strHash &o) const {
strHash res;
res.str.F = (str.F * pw[o.len] + o.str.F) % MP;
res.str.S = (str.S * qw[o.len] + o.str.S) % MQ;
res.rev.F = (o.rev.F * pw[len] + rev.F) % MP;
res.rev.S = (o.rev.S * qw[len] + rev.S) % MQ;
res.len = len + o.len;
return res;
}
}s[MAX_N]; void init() {
pw[] = qw[] = ;
for (int i = ; i < MAX_N; i++) {
pw[i] = pw[i-] * P % MP;
qw[i] = qw[i-] * Q % MQ;
}
} strHash makeHash(const char *str) {
strHash res;
res.len = strlen(str);
res.str.F = res.str.S = ;
for (int i = ; i < res.len; i++) {
res.str.F = (res.str.F * P + str[i]) % MP;
res.str.S = (res.str.S * Q + str[i]) % MQ;
}
res.rev.F = res.rev.S = ;
for (int i = res.len-; ~i; i--) {
res.rev.F = (res.rev.F * P + str[i]) % MP;
res.rev.S = (res.rev.S * Q + str[i]) % MQ;
}
return res;
} /* 判断a+b 或者 b+a是否为回文 */
inline bool check(const strHash &a, const strHash &b) {
strHash u = a + b;
if (u.str == u.rev) return true;
strHash v = b + a;
if (v.str == v.rev) return true;
return false;
} /* 一般图最大匹配(带花树) */
const int MAX = ;
struct GraphMatch {
int Next[MAX];
int spouse[MAX];
int belong[MAX]; int findb(int a) {
return belong[a]==a?a:belong[a]=findb(belong[a]);
}
void together(int a,int b){
a=findb(a),b=findb(b);
if (a!=b)belong[a]=b;
} vector<int> E[MAX];
int N;
int Q[MAX],bot;
int mark[MAX];
int visited[MAX]; int findLCA(int x,int y){
static int t=;
t++;
while () {
if (x!=-) {
x = findb(x);
if (visited[x]==t)return x;
visited[x]=t;
if (spouse[x]!=-)x=Next[spouse[x]];
else x=-;
}
swap(x,y);
}
} void goup(int a,int p){
while (a!=p){
int b=spouse[a],c=Next[b];
if (findb(c)!=p)Next[c]=b;
if (mark[b]==)mark[Q[bot++]=b]=;
if (mark[c]==)mark[Q[bot++]=c]=;
together(a,b);
together(b,c);
a=c;
}
} void findaugment(int s){
for (int i=;i<N;i++) {
Next[i]=-;
belong[i]=i;
mark[i]=;
visited[i]=-;
}
Q[]=s;bot=;mark[s]=;
for (int head=;spouse[s]==- && head<bot;head++){
int x=Q[head];
for (int i=;i<(int)E[x].size();i++){
int y=E[x][i];
if (spouse[x]!=y && findb(x)!=findb(y) && mark[y]!=){
if (mark[y]==){
int p=findLCA(x,y);
if (findb(x)!=p)Next[x]=y;
if (findb(y)!=p)Next[y]=x;
goup(x,p);
goup(y,p);
}else if (spouse[y]==-){
Next[y]=x;
for (int j=y;j!=-;){
int k=Next[j];
int l=spouse[k];
spouse[j]=k;spouse[k]=j;
j=l;
}
break;
}else{
Next[y]=x;
mark[Q[bot++]=spouse[y]]=;
mark[y]=;
}
}
}
}
} void init(int n) {
N = n;
for (int i = ; i < N; ++i) {
E[i].clear();
}
} void addEdge(int a, int b) {
E[a].push_back(b);
E[b].push_back(a);
} int maxMatch() {
int ret = ;
for (int i = ; i < N; ++i) spouse[i] = -;
for (int i = ; i < N; ++i) {
if (spouse[i] == -) {
findaugment(i);
}
}
for (int i = ; i < N; ++i) {
if (spouse[i] != -) ++ret;
}
return ret;
}
} match; int main(void) {
init();
int N;
while (~scanf("%d", &N)) {
for (int i = ; i < N; i++) {
scanf("%s", str);
s[i] = makeHash(str);
} match.init(N);
for (int i = ; i < N; i++) {
for (int j = i+; j < N; j++) {
if (check(s[i], s[j])) {
match.addEdge(i, j);
}
}
}
int cnt = match.maxMatch();
/*
for (int i = 0; i < N; i++) {
printf("%d %d\n", i, match.spouse[i]);
}
*/
printf("%d\n", N - cnt / );
} return ;
}
Joining Byte Blocks(哈希+带花树)的更多相关文章
- [转]带花树,Edmonds's matching algorithm,一般图最大匹配
看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...
- HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力
一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...
- 【Learning】带花树——一般图最大匹配
一般图最大匹配--带花树 问题 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. 这个问题的退化版本就是二分图最大匹配. 由于二分图中不存在奇环,偶环对最大匹配并无 ...
- 【learning】一般图最大匹配——带花树
问题描述 对于一个图\(G(V,E)\),当点对集\(S\)满足任意\((u,v)\in S\),均有\(u,v\in V,(u,v)\in E\),且\(S\)中没有点重复出现,我们称\(S\) ...
- [BZOJ]4405: [wc2016]挑战NPC(带花树)
带花树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...
- 【XSY2774】学习 带花树
题目描述 给你一个图,求最大匹配. 边的描述方式很特殊,就是一次告诉你\(c_i\)个点:\(d_1,d_2,\ldots,d_{c_i}\),表示这些点两两之间都有连边,也就是说,这是一个团.总共有 ...
- HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】
<题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...
- URAL 1099 Work Scheduling (一般图最大匹配) 模板题【带花树】
<题目链接> <转载于 >>> > 题目大意: 给出n个士兵,再给出多组士兵之间两两可以匹配的关系.已知某个士兵最多只能与一个士兵匹配.求最多能够有多少对匹 ...
- BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配
https://www.lydsy.com/JudgeOnline/problem.php?id=4405 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...
随机推荐
- 0920CSP-S模拟测试赛后总结
依旧挂了. 这次出题人十分良心.白送了180分……于是我没有拿到.130分rank43滚粗了. T1是道sbdp.然而我死想哈希.然后就死在哈希上了. 我简直是个傻子.之前考了几次字符串的题可以用哈希 ...
- arcmap分类标注问题
在给图层标注的时候,经常出现冲突后有些标注出不来,需要将某些个别的点要素进行标注位置调整,如下图: 处理步骤如下, (1)打开Maplex标注引擎.从ToolBars中打开Labeling工具,勾选U ...
- VS2010-MFC(常用控件:图片控件Picture Control)
转自:http://www.jizhuomi.com/software/193.html 本节主要讲一种简单实用的控件,图片控件Picture Control.我们可以在界面某个位置放入图片控件,显示 ...
- Django的日常-AJAX
目录 Django的日常-AJAX AJAX简介 AJAX与JQ的一个实例 AJAX与contentType AJAX传json格式 AJAX传文件 Django的日常-AJAX AJAX简介 首先A ...
- 炮兵阵地 /// 状压DP oj26314
题目大意: 炮兵阵地 设置炮兵的位置 其上两位 下两位 左两位 右两位 不能同时设置炮兵 这题是 corn fields玉米地 的升级版 可以先看下这题的注释 更详细些 第一种方法是网上大多数题解的解 ...
- 基于jdk8的格式化时间方法
背景 jdk8之前,java使用Date表示时间,在做时间的格式化时,通常使用SimpleDateFormat,但是SimpleDateFormat是非线程安全的,在写代码时通常要将之定义为局部变量或 ...
- 3.在vm上安装centos 7
在vm上安装centos 7 1.文件 → 新建虚拟机 3.选择安装Linux系统 4. 虚拟机命名,并选择安装的文件夹 5.选择分配的处理器 6.使用网络地址转换 7.默写选项 9.新建虚拟机 10 ...
- 历经小半宿吧。哎,终于搭建好了Linux-C的环境
小小地庆祝一下吧 继续努力学习,把Linux-C熟悉一下,争取做到会用吧... 我想应该不难 我熟悉的 iostream 还存在 可惜,微软基础类库不在了...
- 最全Linux常用命令大全
查看系统系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMB ...
- 【默默努力】vue-pc-app
最近在github上面看到了一个团队的项目,真的非常赞.他们进行vue-cli的二次开发,将项目用自己的方式打包. 今天的这个开源项目地址为:https://github.com/tffe-team/ ...