Meeting-in-the-Middle,又称“中途相遇法”。准确地说,它只是一种策略。

顺便说一下,这个算法真的很冷门!

结合这道题来讨论一下吧:LA 2965。ε(┬┬﹏┬┬)3

因为博主的英文实在是十分拙劣,所以只能给出题目大意:

题目大概是说,输入多组数据(组数未知 反正不多啦),每组给定一个$k<=24$,代表有k个字符串。

然后每组的后k行,依次输入这么多个字符串。

要求你选择尽量多的字符串,使得被选的字符串中的所有字母中,每种字母都出现偶数次。

输出选择字符串数,并从小到大输出被选字符串。

给组样例吧:

in

ABC

ABD
EG
GE
ABE
AC
BCD

out


      

这个题目,乍一看上去,博主就只想到了模拟。。。(博主蒟蒻一枚)。

事实上,仔细分析,我们会发现:

这个题目,和字母的个数实际上没多大关系,更多的是和字母出现次数的奇偶有关。

于是我们假设有这么一张表:(拿样例中k=6的那一组为例)

A B C D E F G H……
……
……
……
……
……
…… 

代表什么呢?显然这个表上的每一行都是一个26为的二进制数,而每一位对应一个字母,代表这个字母在此串中出现次数的奇或偶。

1代表的是奇,0代表的是偶。

仔细想想,我们是不是只要这么做:选择尽量多的串,使其异或值为0。

好。有了这张表,这就好办了。我们可以进行暴力穷举法$O(2^n)$。是不是还是很low?显然,这个时间复杂度过不了规模高达24的数据。

那么,我们怎么办呢?

这时候,我们开始讲到的MITM策略就可以派上用场了。

别看它的名字这么高级,其实思想主要是:

将待测数据(也就是那张表)分成两部分,枚举上表的所有子集的xor值,放入一个hash表或者map映射里。

然后枚举后半部分的数据所能得到的所有xor值,并每次都在hash表或者map映射里查找。

如果用map实现的话,总时间复杂度为$O(2^{(n/2)}logn)$,即$O(1.414^nlogn)$,比第一种方法好了很多。

这就是Meeting-in-the-Middle中途相遇法。

据刘汝佳神犇所述:密码学中的著名的中途相遇攻击(Meeting-in-the-Middle attack)就是基于这个原理。

最后贴上代码吧:

#include <bits/stdc++.h>
using namespace std; const int maxn=;
map <int,int> table; int bitcount(int x) {
return x==?:bitcount(x/)+(x&);
}//这个函数用来计算这个数在二进制下有多少个1 int main()
{
int n,A[maxn];
char s[];
while (scanf("%d",&n)==&&n) {//读入多组数据
for (int i=;i<n;i++) {
scanf("%s",s);//输入字符串
A[i]=;
for (int j=;s[j]!='\0';j++)
A[i]^=(<<(s[j]-'A'));//计算每一串的<=26位二进制值
}
table.clear();//清空table映射
int n1=n/,n2=n-n1;//将待测数据分成两部分 //接下来循环计算2^(n/2)个属于前半部分的子集
for (int i=;i<(<<n1);i++) {
int x=;
for (int j=;j<n1;j++)
if (i&(<<j)) x^=A[j];
if (!table.count(x)||bitcount(table[x])<bitcount(i))
table[x]=i;
}//取每个计算结果中的最大值 //最后处理后半部分
int ans=;
for (int i=;i<(<<n2);i++) {
int x=;
for (int j=;j<n2;j++)
if (i&(<<j)) x^=A[n1+j];
if (table.count(x)&&bitcount(ans)<bitcount(table[x])+bitcount(i))
ans=(i<<n1)^table[x];
}//每次计算前查找映射中是否出现过
printf("%d\n",bitcount(ans));
for (int i=;i<n;i++)
if (ans&(<<i)) printf("%d ",i+);
printf("\n");//输出部分
}
return ;
}

如果不用map也可以改成哈希(hash):

int insHash(int x)
{
int c=x%MOD;
for (int u=h[c];u;u=nexp[u])
if (val[u]==x) return u;
if (!gans)
nexp[p]=h[c],h[c]=p,val[p]=x,p++;
return -(p-);
}

然后听机房一位神犇说,这题用深搜(dfs)枚举子集会更快,虽然不知为何?

void dfs(int f,int sum,int k)
{
if (f>upb){
if (sum==-) return;
x=insHash(sum);
if (!gans) {
if (x<) x=-x;
if (k>cnt[x]) cnt[x]=k;
}
else if (x>&&cnt[x]+k>ans)
ans=cnt[x]+k;
else if (!sum&&k>ans) ans=k;
return;
}
dfs(f+,sum==-?num[f]:sum^num[f],k+);
dfs(f+,sum,k);
}

Meeting-in-the-Middle (LA 2965)的更多相关文章

  1. LA 2965 Jurassic Remains

    这是我做的第一道状态压缩的题目,而且我自己居然看懂了,理解得还算透彻. 题意:给出若干个大写字母组成的字符串,然后选取尽量多的字符串使得这些字母出现偶数次. 最朴素的想法,穷举法:每个字符串只有选和不 ...

  2. LA 2965 Jurassic Remains (中途相遇法)

    Jurassic Remains Paleontologists in Siberia have recently found a number of fragments of Jurassic pe ...

  3. UVa LA 2965 - Jurassic Remains 中间相遇,状态简化 难度: 2

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  4. LA 2965 中途相遇法

    题目链接:https://vjudge.net/problem/UVALive-2965 题意: 有很多字符串(24),选出一些字符串,要求这些字符串的字母都是偶数次: 分析: 暴力2^24也很大了, ...

  5. 【中途相遇+二进制】【NEERC 2003】Jurassic Remains

    例题25  侏罗纪(Jurassic Remains, NEERC 2003, LA 2965) 给定n个大写字母组成的字符串.选择尽量多的串,使得每个大写字母都能出现偶数次. [输入格式] 输入包含 ...

  6. 暑期培训7日游解题思路(day1~day3)

    暑期培训7日游解题思路(day1~day3) day1 第一天,王聿中老师出的题目比较简单,T1很水,T2是个简单的DP,T3还是有一点意思的.在网格图中删掉若干条边,使得所有格子都联通,求删掉的边的 ...

  7. SPOJ11469 SUBSET

    题面 Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk each day ...

  8. UVALive - 2965 Jurassic Remains (LA)

    Jurassic Remains Time Limit: 18000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Sub ...

  9. Technical Committee Weekly Meeting 2016.06.21

    Meeting time: 2016.June.21 1:00~2:00 Chairperson:  Thierry Carrez Meeting summary: 1.Add current hou ...

随机推荐

  1. zabbix自动化监控之自动注册

    自动注册与自动发现刚好相反,是zabbix agent主动联系zabbix server,最后由zabbix server将这些agent加到host里.活动的Zabbix agent可以自动注册到服 ...

  2. AcpectJ注释方式配置AOP

    1.AspectJ的概念   @AspectJ类似于Java注解的普通Java类   Spring可以使用AspectJ来做切入点解析   AOP的运行时仍旧是纯的Spring AOP,对Aspect ...

  3. 【Scala-ML】怎样利用Scala构建并行机器学习系统

    引言 在学习Scala的过程中,我发现其在构建大规模分布式计算系统上有与生俱来的特质. 其丰富的类型系统能够帮助编程设计提供非常好的信息隐藏和抽象,其monoids和monads概念利用Scala高阶 ...

  4. XJTU Summer Holiday Test 1(Brackets in Implications-构造)

    B - Brackets in Implications Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  5. hibernate学习系列-----(5)hibernate基本查询下篇:hibernate聚合函数、分组查询及命名查询

    在上一篇中,大致学习了hibernate的基本查询:HQL基本查询,今天,继续昨天的步伐,继续学习hibernate的基本查询..... 1.hql聚合函数,先大致列一下hql的聚合函数有哪些吧: 在 ...

  6. Highcharts使用二维数组生成图表

    Highcharts使用二维数组生成图表 二维数组是更为灵活的一种数据存储方式.在Highcharts中.能够使用配置项column和rows二维数组.对于使用columns构建的二维数组,Highc ...

  7. 重入锁的好搭档:Condition条件(读书笔记)

      Condition结构提供了基本方法如下: void await() throws InterruptedException; void awaitUninterruptibly(); long ...

  8. 在 Linux 系统下使用 PhotoRec & TestDisk 工具来恢复文件

    当你在系统中有意或无意地使用 shift + delete 组合键.删除选项,或是清空回收站的方式来删除一个文件时,该文件的内容并没有从硬盘(或是其它存储设备)上直接销毁. 它仅仅是从系统的目录结构中 ...

  9. JDBC技术总结(一)

    1. JDBC简介 SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC,JDBC不能直接操作数据库,JDBC通过接口加载数据库的驱动,然后操作数据库.JDBC: ...

  10. IBM Rational Appscan使用之扫描结果分析

    转自:http://www.nxadmin.com/penetration/825.html 之前有IBM Rational Appscan使用详细说明的一篇文章,主要是针对扫描过程中配置设置等.本文 ...