题目链接

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(哈希+带花树)的更多相关文章

  1. [转]带花树,Edmonds's matching algorithm,一般图最大匹配

    看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...

  2. HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

    一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...

  3. 【Learning】带花树——一般图最大匹配

    一般图最大匹配--带花树 问题 ​ 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. ​ 这个问题的退化版本就是二分图最大匹配. ​ 由于二分图中不存在奇环,偶环对最大匹配并无 ...

  4. 【learning】一般图最大匹配——带花树

    问题描述 ​ 对于一个图\(G(V,E)\),当点对集\(S\)满足任意\((u,v)\in S\),均有\(u,v\in V,(u,v)\in E\),且\(S\)中没有点重复出现,我们称\(S\) ...

  5. [BZOJ]4405: [wc2016]挑战NPC(带花树)

    带花树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...

  6. 【XSY2774】学习 带花树

    题目描述 给你一个图,求最大匹配. 边的描述方式很特殊,就是一次告诉你\(c_i\)个点:\(d_1,d_2,\ldots,d_{c_i}\),表示这些点两两之间都有连边,也就是说,这是一个团.总共有 ...

  7. HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】

    <题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...

  8. URAL 1099 Work Scheduling (一般图最大匹配) 模板题【带花树】

    <题目链接> <转载于 >>>  > 题目大意: 给出n个士兵,再给出多组士兵之间两两可以匹配的关系.已知某个士兵最多只能与一个士兵匹配.求最多能够有多少对匹 ...

  9. BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配

    https://www.lydsy.com/JudgeOnline/problem.php?id=4405 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...

随机推荐

  1. csps模拟87888990部分题解

    题面:https://www.cnblogs.com/Juve/articles/11752338.html https://www.cnblogs.com/Juve/articles/1175241 ...

  2. 计算几何——线段和直线判交点poj3304

    #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #i ...

  3. 运用shtml类型文件,实现项目页面的分割。

    学过动态网页,如asp.php的人知道如何去引用网站头部.底部文件包含.例如在php中有一个方法:include();这个方法能在当前文档中引入外部文件,从而方便网站的开发和维护,然而html静态文件 ...

  4. System.Web.HttpCookie.cs

    ylbtech-System.Web.HttpCookie.cs 1.程序集 System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken= ...

  5. iOS扩展Extension之Today

    1.简介 扩展(Extension)是iOS 8中引入的一个新特性.扩展让app之间的数据交互成为可能.在iOS 8系统之前,每一个app在物理上都是彼此独立的,app之间不能互访彼此的私有数据.而在 ...

  6. 19.SimLogin_case05

    # 使用自造的cookies登录马蜂窝 import requests from lxml import etree str = 'mfw_uuid=5bcfcc20-b235-fbbe-c1d6-a ...

  7. 7_2.springboot2.x启动配置原理_2.运行run方法

    当创建完SpringApplication对象之后运行run方法 public ConfigurableApplicationContext run(String... args) { StopWat ...

  8. <Django>socket简单实现django简化版

    服务端(自己实现django) ''' django简化版:socket服务端 a.收发浏览器信息----wsgiref.py b.根据用户访问的不同路径执行不同函数 c.从html读取出内容,并完成 ...

  9. [JZOJ4648] 【NOIP2016提高A组模拟7.17】锦标赛

    题目 描述 题目大意 有nnn个人,你要确定一个出场序列.每次新上台的人就会和擂主打一架,胜利的人继续当擂主.题目给出两两之间打架胜利(失败)的概率. 问111选手坚持到最后的最大概率. 思考历程 看 ...

  10. 3、变量+运算符+Scanner

    1.变量 1>开辟内存空间 int num ; 2>赋值 num = 10; 3>使用 num 1*long 类型的特殊 long num = 12L 2*float类型特殊 flo ...