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 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...
随机推荐
- LUOGU P2564 [SCOI2009]生日礼物 (队列+模拟)
传送门 解题思路 还是比较好想的,用一个队列,然后把所有点放在一起排个序,依次入队.每次检查队头元素的种类是否为当前入队元素种类,是的话就一直\(pop\),每次更新答案即可. 代码 #include ...
- 双线程DP
1.传纸条 好像是一道普及组水题? //Twenty #include<cstdio> #include<iostream> #include<cstring> # ...
- 牛客多校第五场 A digits 2 签到
题意: 给定一个n,输出一个数,要求这个数所有位之和整除n,并且这个数也整除n,并且位数不许多于1e4 题解: 把这个数n输出n遍. #include<iostream> using na ...
- 尚学python课程---13、python基础语法
尚学python课程---13.python基础语法 一.总结 一句话总结: legend2系统使我能够快速掌握一门语法,特别有用 pass 语句:空语句:是为了保持程序结构的完整性 :作用:比如: ...
- mysql索引原理深度解析
mysql索引原理深度解析 一.总结 一句话总结: mysql索引是b+树,因为b+树在范围查找.节点查找等方面优化 hash索引,完全平衡二叉树,b树等 1.数据库中最常见的慢查询优化方式是什么? ...
- VC6 Release下,生成pdb文件
1.Generate debug必须选上,否则没有调试信息 2.把优化disable,否则容易产生代码地址偏移: 3.用program database产生PDB文件: 4.将dll, exe, pd ...
- System.Web.Mvc.HttpDeleteAttribute.cs
ylbtech-System.Web.Mvc.HttpDeleteAttribute.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral ...
- PAT甲级——A1126 Eulerian Path【30】
In graph theory, an Eulerian path is a path in a graph which visits every edge exactly once. Similar ...
- Map、可变参数、静态导入、Collections、Arrays、集合嵌套
Map双列集合 key 键 value 值 方法: put(K, V) //判断key值是否相等,相等,覆盖元素,不相等,存储 remove(K) Map集合的遍历(不要看到java提供了很多方法做一 ...
- WPF基础之Grid面板
一.显示 Grid的线条,设置ShowGridLiens="True".