论一类脑筋急转弯题和奇技淫巧题的解题技巧

【题意】

给定n个长为m且只包含xyz的字符串,定义两个字符串的相似程度为它们对应位置相同字符个数(比如xyz和yyz的相似程度为2,后两位相同),分别求出相似度为0~m的无序字符串对数。

【样例】

输入:

4 3

xyz

xyz

zzx

xzz

输出:

2

1

2

1

解释:

(xyz,zzx)(xyz,zzx)相似度为0,(zzx,xzz)相似度为1,(xyz,xzz) (xyz,xzz)相似度为2,(xyz,xyz)相似度为3。

【数据范围与约定】

共20个测试点。

对于测试点1,n<=10。

对于测试点2,3,n*m≤1000。

对于测试点4,所有单词都相同。

对于测试点5,m=1。

对于测试点6~10,所有单词只包含x和y这两个字符。

对于全部测试点,n*m<=100000。

注意时间限制是3s。

【解法】

不得不说这个题的解法真特么机智……脑筋急转弯……

先想暴力,暴力枚举C(n,2)个字符串对,每个对都用O(m)的时间暴力比较,复杂度O(n2m)。

观察一下数据范围,n*m<=100000。换句话说,m>30的时候直接暴力即可(经计算m=31时n2m=322419375,况且还有0.5的常数,实测无压力)。剩下的就只有m<=30的情况了。

如果换个方向考虑,可以发现字符串的种类是有限的(最多3m种)。所以,可以尝试对字符串三进制状压,然后只需枚举一遍字符串并从之前的所有3m种字符串中枚举获得答案即可。这样的复杂度是O(n3m),对于m=30的情况来说实在是太大了,经计算大概只能到m=7~8的级别(m=8时n3m=82012500,m=9时n3m=328036878,由于三进制常数比较大,实际上m=7的时候就已经T了,当然你也可以用四进制减小常数)。

这样就麻烦了,m<7的时候可以三进制暴力,m>30的时候可以直接暴力,中间那些7<=m<=30的情况怎么搞?

回过头来看暴力,对于每个字符串对我们是用暴力比较的方式得出相似度的。但其实没这个必要,m<=30的时候完全可以把它压成三个二进制数x,y,z,分别表示对应位为x,y,z的下标集合。这样比较的时候就可以用二进制位运算O(1)得出两串的相同部分的集合(也是二进制数),再O(1)数出里面的1的个数,比较就压到O(1)了。至于统计1个数,我用的是14年沈洋论文里的递推法,具体可以看沈洋的论文。

最后总结解法:

对于不同的m分类讨论。

m<7时,三进制状压暴力。

7<=m<=30时,压位后暴力。

m>30时,直接暴力。

贴个代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define cntone(x) ((one[((x)&(65535))])+(one[((x)>>(16))]))
using namespace std;
const int maxn=;
int n,m,one[maxn]={},cnt[maxn]={},x[maxn],y[maxn],z[maxn],pw[maxn];
long long ans[maxn]={};
char c[maxn];
string s[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%s",c);
s[i]=c;
}
if(m<){
pw[]=;
for(int i=;i<=m;i++)pw[i]=pw[i-]*;
for(int i=;i<=n;i++){
int val=;
for(int j=;j<m;j++)val=val*+s[i][j]-'x';
for(int k=;k<pw[m];k++){
int tmp=;
for(int j=;j<m;j++)if((k/pw[j])%==(val/pw[j])%)tmp++;
ans[tmp]+=cnt[k];
}
cnt[val]++;
}
}
else if(m<){
for(int i=;i<;i++)one[i]=one[i>>]+(i&);
for(int i=;i<=n;i++){
for(int j=;j<m;j++){
if(s[i][j]=='x')x[i]|=<<j;
else if(s[i][j]=='y')y[i]|=<<j;
else z[i]|=<<j;
}
for(int j=;j<i;j++)ans[cntone((x[i]&x[j])|(y[i]&y[j])|(z[i]&z[j]))]++;
}
}
else{
for(int i=;i<=n;i++)for(int j=;j<i;j++){
int tmp=;
for(int k=;k<m;k++)if(s[i][k]==s[j][k])tmp++;
ans[tmp]++;
}
}
for(int i=;i<=m;i++)printf("%lld\n",ans[i]);
return ;
}

【后记】

好像m>30的时候也可以压位优化(多压几个int),不过懒得写了。

这题真特么脑筋急转弯……被今天的三道脑筋急转弯题坑惨了……

单词words的更多相关文章

  1. java统计字符串单词的个数

    在一些项目中可能需要对一段字符串中的单词进行统计,我在这里写了一个简单的demo,有需要的同学可以拿去看一下. 本人没怎么写个播客,如果有啥说的不对的地方,你来打我啊 不说废话了直接贴代码: 实现代码 ...

  2. JavaScript将字符串中的每一个单词的第一个字母变为大写其余均为小写

    要求: 确保字符串的每个单词首字母都大写,其余部分小写. 这里我自己写了两种方法,或者说是一种方法,另一个是该方法的变种. 第一种: function titleCase(str) { var new ...

  3. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  4. [LeetCode] Concatenated Words 连接的单词

    Given a list of words (without duplicates), please write a program that returns all concatenated wor ...

  5. [LeetCode] Word Squares 单词平方

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...

  6. [LeetCode] Valid Word Square 验证单词平方

    Given a sequence of words, check whether it forms a valid word square. A sequence of words forms a v ...

  7. [LeetCode] Minimum Unique Word Abbreviation 最短的独一无二的单词缩写

    A string such as "word" contains the following abbreviations: ["word", "1or ...

  8. [LeetCode] Valid Word Abbreviation 验证单词缩写

    Given a non-empty string s and an abbreviation abbr, return whether the string matches with the give ...

  9. [LeetCode] Maximum Product of Word Lengths 单词长度的最大积

    Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the tw ...

  10. [LeetCode] Unique Word Abbreviation 独特的单词缩写

    An abbreviation of a word follows the form <first letter><number><last letter>. Be ...

随机推荐

  1. concat() 方法用于连接两个或多个数组。

    我们创建了三个数组,然后使用 concat() 把它们连接起来: <script type="text/javascript"> var arr = new Array ...

  2. java构造方法的作用以及简单java类

    public class TestDemo{ public static void main(String args[]){ Emp emp1 =new Emp(001,"tom" ...

  3. 【ASP.NET实战教程】基于ASP.NET技术下多用户博客系统全程实战开发(NNblog)

    岁末主推:牛牛老师主讲,多用户博客系统,基于ASP.NET技术,年后将带来移动业务平台项目项目目标: 打造个性品牌Blogo,定制多用户博客 为每一个博客用户提供个性化的 blogo解决方案,打造精品 ...

  4. 缩小窗口时CSS背景图出现右侧空白BUG的解决方法

    页面容器(#wrap)与页面头部(#header )为100%宽度.而内容的容器(#page)为固定宽度960px.浏览窗口缩小而小于内容层宽度时会产生宽度理解上的差异.如下图所示窗口宽度大于内容层宽 ...

  5. Jquery DIV滚动至浏览器顶部位置固定

    获取元素(这里定位元素A)距离顶部的高度,接着设定scroll滚动的事件,比如超过那个高度,把A的位置设定为fixed,小于该高度,修改回relative. 方法一: $(function() { v ...

  6. 搭建TFS 2015 Build Agent环境(二)

    在执行和安装配置的过程中,注意一定要使用管理员权限运行:ConfigureAgent.cmd 和RunAgent.cmd.配置的过程中,要注意几个内容:1.TFS地址不要写DefaultCollect ...

  7. 中文乱码?不,是 HTML 实体编码!

    When question comes 在 如何用 Nodejs 分析一个简单页面 一文中,我们爬取了博客园首页的 20 篇文章标题,输出部分拼接了一个字符串: var $ = cheerio.loa ...

  8. 利用Microsoft.Practices.Unity的拦截技术,实现.NET中的AOP

    1.记住这个单词的意思:Interception(拦截) 2.首先说一下原理和背景 原理:所谓的AOP就是面向切面编程,这里不多说,百度搜索. 目的:个人认为是为了解耦,部分代码跟业务代码分离,业务代 ...

  9. js base64加密,后台解密

    这是为了解决页面发送post请求,传输密码,在页面的控制台可以看到密码的明文,所以先用base64把要传输的密码转换为非明文,然后在后台解密处理. base64encode.js // base64加 ...

  10. 使用StackExchange.Redis客户端进行Redis访问出现的Timeout异常排查

    问题产生 这两天业务系统在redis的使用过程中,当并行客户端数量达到200+之后,产生了大量timeout异常,典型的异常信息如下: Timeout performing HVALS Parser2 ...