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 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...
随机推荐
- SpringBoot-application:application.yml/配置文件详解
ylbtech-SpringBoot-application:application.yml/配置文件详解 springboot采纳了建立生产就绪spring应用程序的观点. Spring Boot优 ...
- 云-腾讯云-云通信:云通信(IM)
ylbtech-云-腾讯云-云通信:云通信(IM) 企业数字化转型的通信助手,让通信触达全球,智联万物 1.返回顶部 1. 云通信(Instant Messaging,IM)承载亿级 QQ 用户即时通 ...
- 理解云计算三种服务模式——IaaS、PaaS和SaaS
云计算的服务模式仍在不断进化,但业界普遍接受将云计算按照服务的提供方式划分为三个大类: SaaS(Software as a Service–软件即服务) PaaS(Platform as a Ser ...
- windows 映射samba Linux服务器,输入正确的账号密码却提示“ 指定的网络密码不正确
重启Linux samba服务也没用,重启Linux和windows系统也没用,急!!! 最佳答案 linux中要添加对应的系统用户和samba用户useradd titiansmbpasswd -a ...
- day 61 Django基础之django分页
Django基础之django分页 一.Django的内置分页器(paginator) view from django.shortcuts import render,HttpRespons ...
- [kuangbin带你飞]专题一 简单搜索 - A - 棋盘问题
#include<iostream> #include<cstdio> #include<string> #include<vector> #inclu ...
- python+appium真机运行登录例子
一.手机USB连接电脑(手机打开调试模式) 验证:cmd -> 输入adb devices,查看手机的UDID.显示如下表示 连接成功 二.启动Appium服务 1. 启动Appium,点击 右 ...
- vue项目导出EXCEL功能
因为一些原因导出EXCEL功能必须前端来做,所以就研究了一下,在网上也找了一些文章来看,有一些不完整,我做完了就记录下来,供大家参考: 1.首先先安装依赖: npm install file-save ...
- java_增强for循环
增强for循环(foreach): 底层使用了迭代器,简化了迭代器的书写 JDK1.5新特性 所有的单列集合都可以使用增强for循环 for(集合/数组 的数据类型 变量名 : 集合名/数组名) pu ...
- C++ AOP手法
1.代理模式 2.模版 3.NVI(non-virtual interface) 参考:https://www.cnblogs.com/qicosmos/p/4772389.html <effe ...