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 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...
随机推荐
- nginx css,js合并插件,淘宝nginx合并js,css插件
先下载Nginx_concat_module,下载后把它放在/usr/local/src/文件夹中,新建文件夹nginx-http-concat把下载的config ngx_http_concat_ ...
- [SNOI 2017] 炸弹
题目描述: 给定炸弹和爆炸范围,求对于每个炸弹连锁爆炸的炸弹总和对\(1e9+7\)取膜 思路: 为啥都是线段树+TS+tarjan呢? 实在是搞不懂~~ 线性\(O(n)\)递推即可. #inclu ...
- DELPHI指针的使用
DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...
- Python中好用的模块们
目录 Python中好用的模块们 datetime模块 subprocess模块 matplotlib折线图 importlib模块 Python中好用的模块们 datetime模块 相信我们都使 ...
- POJ - 3294~Relevant Phrases of Annihilation SPOJ - PHRASES~Substrings POJ - 1226~POJ - 3450 ~ POJ - 3080 (后缀数组求解多个串的公共字串问题)
多个字符串的相关问题 这类问题的一个常用做法是,先将所有的字符串连接起来, 然后求后缀数组 和 height 数组,再利用 height 数组进行求解. 这中间可能需要二分答案. POJ - 3294 ...
- 复杂Linq语句写法
从网上收藏的复杂Linq语句写法 1.case when: 原型: sql原型: SELECT ProductID, Name, Color, CASE WHEN Color = 'Red' THEN ...
- JAVA中日期 yyyy-MM-dd HH:mm:ss和yyyy-MM-dd hh:mm:ss的区别
HH是24小时制,hh是12小时制 区别就是:大写的H是二十四小时制的小时数(0-23),小写的h是十二小时制的小时数(am/pm 1-12) //24小时制 SimpleDateFormat sdf ...
- JS流程控制语句 多种选择(Switch语句) 当有很多种选项的时候,switch比if else使用更方便。
多种选择(Switch语句) 当有很多种选项的时候,switch比if else使用更方便. 语法: switch(表达式) { case值1: 执行代码块 1 break; case值2: 执行代码 ...
- 【学术篇】SPOJ-DISQUERY
一道傻逼链剖我TM总共差不多写了一小时,调了将近一天!!!!!! 题目传送门:http://www.spoj.com/problems/DISQUERY/ 嗯,偷偷递小广告:SPOJ是个挺好的OJ ( ...
- 嘴巴题9 Codeforces 453A. Little Pony and Expected Maximum
A. Little Pony and Expected Maximum time limit per test 1 second memory limit per test 256 megabytes ...