LA4671 K-neighbor substrings(FFT + 字符串Hash)
题目
Source
http://acm.hust.edu.cn/vjudge/problem/19225
Description
The Hamming distance between two strings of the same length is defined as the number of positions at which the corresponding characters are different. For example, the Hamming distance between “abbab” and “bbabb” is 3.
A string is called a K-neighbor of another string if and only if they are of the same length and the Hamming distance between them is not larger than K. In this problem, given an integer K and two strings A and B which only contain character ‘a’ and ‘b’, you are to count how many different sub-strings of A are K-neighbors of B.
Input
The input consists of multiple test cases. Each test case starts with a line containing one integer K (0 ≤ K ≤ 100, 000).
The following two lines give two non-empty strings consisting of ‘a’ and ‘b’, which are string A and string B, respectively.
The length of strings A and B will both lie between 1 and 100,000, inclusive. The last test case is followed by a line containing one ‘-1’.
Output
For each test case, print a line containing the test case number (beginning with 1) followed by the number of different sub-strings of string A which are K-neighbors of string B.
Sample Input
0
aabbab
ab
1
aabbab
ab
2
aabba
ab
-1
Sample Output
Case 1: 1
Case 2: 3
Case 3: 4
分析
题目大概说给两个由'a'和'b'组成的字符串A和B,问A有几个不同的子串满足其长度等于B且与B各个对应位置不同的字符总数不超过k。
颠倒数组转化成可以用FFT解决的卷积形式。。原来是这么个意思。
http://blog.csdn.net/pure_lady/article/details/48749635
假设len(B)=n,将B翻转,然后A与B对应位置就是A[x]与B[n-1]、A[x+1]与B[n-2]、...、A[x+n-1]与B[0],可以发现(x)+(n-1) = (x+1)+(n-2) = ... = (x+n-1)+(0),类似多项式乘法。
然后如果把'a'作为1,'b'作为0,字符串各个位置作为指数,表示出A和反转的B的两个多项式,用FFT求出乘积,即类似这种ΣA(i)B(n-i)卷积形式,最后得出这个乘积的结果中指数为x+(n-1)(0<=x<len(A)-(n-1))的系数就表示A中以x+(n-1)结尾的子串有多少个'a'与B串对应位置相同;
把'b'作为1,'a'作为0作同样处理即可同样得出A中各个子串'b'对应位置相同的个数。
感觉还是挺神奇的。。
这样不同个数不超过k就相当于相同个数大于等于len(B)-k。不过问题要求的是不同的子串,还要去掉重复的。。
可以用字符串Hash做。。字符串Hash我是乱搞的,改了几个值,改了模数,又尝试了双重hash。。WA又TLE十多次后,最后终于AC了。。
其实我不会字符串Hash,全都是乱搞的= =。。
不过后缀数组也是可以做的,本来要放弃改用后缀数组的,没想到居然AC了。。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<set>
#include<algorithm>
using namespace std;
#define MAXN 277777
#define MOD 9999999967LL
const double PI=acos(-1.0); struct Complex{
double real,imag;
Complex(double _real,double _imag):real(_real),imag(_imag){}
Complex(){}
Complex operator+(const Complex &cp) const{
return Complex(real+cp.real,imag+cp.imag);
}
Complex operator-(const Complex &cp) const{
return Complex(real-cp.real,imag-cp.imag);
}
Complex operator*(const Complex &cp) const{
return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
}
void setValue(double _real=0,double _imag=0){
real=_real; imag=_imag;
}
}; int len;
Complex wn[MAXN],wn_anti[MAXN]; void FFT(Complex y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
for(int h=2; h<=len; h<<=1){
Complex Wn=(op==1?wn[h]:wn_anti[h]);
for(int i=0; i<len; i+=h){
Complex W(1,0);
for(int j=i; j<i+(h>>1); ++j){
Complex u=y[j],t=W*y[j+(h>>1)];
y[j]=u+t;
y[j+(h>>1)]=u-t;
W=W*Wn;
}
}
}
if(op==-1){
for(int i=0; i<len; ++i) y[i].real/=len;
}
}
void Convolution(Complex A[],Complex B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i].setValue();
B[i].setValue();
}
FFT(A,1); FFT(B,1);
for(int i=0; i<len; ++i){
A[i]=A[i]*B[i];
}
FFT(A,-1);
} char s1[111111],s2[111111];
int cnt[MAXN];
Complex A[MAXN],B[MAXN]; int main(){
for(int i=0; i<277777; ++i){
wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
wn_anti[i].setValue(wn[i].real,-wn[i].imag);
}
int k,cse=0;
while(scanf("%d",&k)==1 && k!=-1){
scanf("%s%s",s1,s2);
int n1=strlen(s1),n2=strlen(s2); if(n1<n2){
printf("Case %d: 0\n",++cse);
continue;
} for(int i=0; i<n1; ++i){
if(s1[i]=='a') A[i].setValue(1);
else A[i].setValue(0);
}
for(int i=0; i<n2; ++i){
if(s2[i]=='a') B[n2-i-1].setValue(1);
else B[n2-i-1].setValue(0);
}
for(int i=n2; i<n1; ++i){
B[i].setValue(0);
}
Convolution(A,B,n1);
for(int i=0; i<len; ++i){
cnt[i]=(int)(A[i].real+0.5);
} for(int i=0; i<n1; ++i){
if(s1[i]=='b') A[i].setValue(1);
else A[i].setValue(0);
}
for(int i=0; i<n2; ++i){
if(s2[i]=='b') B[n2-i-1].setValue(1);
else B[n2-i-1].setValue(0);
}
for(int i=n2; i<n1; ++i){
B[i].setValue(0);
}
Convolution(A,B,n1);
for(int i=0; i<len; ++i){
cnt[i]+=(int)(A[i].real+0.5);
} k=n2-k; int tot=0;
long long h=0,mi=1;
set<long long> hash;
for(int i=0; i<n2-1; ++i){
h=(h*8887+s1[i]*3)%MOD;
mi*=8887; mi%=MOD;
}
for(int i=n2-1; i<n1; ++i){
h=(h*8887+s1[i]*3)%MOD;
if(hash.count(h)==0){
if(cnt[i]>=k) ++tot;
hash.insert(h);
}
h-=(s1[i-n2+1]*3*mi)%MOD;
h%=MOD; if(h<0) h+=MOD;
}
printf("Case %d: %d\n",++cse,tot);
}
return 0;
}
LA4671 K-neighbor substrings(FFT + 字符串Hash)的更多相关文章
- codeforces gym 101164 K Cutting 字符串hash
题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #prag ...
- POJ 3865 - Database 字符串hash
[题意] 给一个字符串组成的矩阵,规模为n*m(n<=10000,m<=10),如果某两列中存在两行完全相同,则输出NO和两行行号和两列列号,否则输出YES [题解] 因为m很小,所以对每 ...
- 【邻接表字符串Hash】【HDU1800】Flying to the Mars
题意: 给你N个数字,带前导0,问出现最多的数字个数 思路: 读入,清楚前导0,Hash. 用邻接表字符串Hash有一下几点注意 string,不要memset,否则地址也没了,涉及到stl的东西,少 ...
- CodeForces - 727E Games on a CD 字符串Hash
题意:有n个单词,每个单词长度为k,顺时针将它们写成一个圆圈串.现在知道g个长度为k的单词,是否可以从这g个单词中选择n个形成这个圆圈串?如果有多个答案,任意输出一个. 思路 可以发现,如果枚举第一个 ...
- HDU-魔咒词典(字符串hash)
魔咒词典 TimeLimit: 8000/5000 MS (Java/Others) MemoryLimit: 32768/32768 K (Java/Others) 64-bit integer ...
- Palindrome POJ - 3974 (字符串hash+二分)
Andy the smart computer science student was attending an algorithms class when the professor asked t ...
- CodeForces7D 字符串hash + dp
https://cn.vjudge.net/problem/20907/origin 长度是 n 的字符串 s,如果它自身是回文数,且它的长度为 的前缀和后缀是 (k - )-回文数,则它被称作 k- ...
- 【题解】 Codeforces Edu44 F.Isomorphic Strings (字符串Hash)
题面戳我 Solution 我们按照每个字母出现的位置进行\(hash\),比如我们记录\(a\)的位置:我们就可以把位置表示为\(0101000111\)这种形式,然后进行字符串\(hash\) 每 ...
- CH 1402 - 后缀数组 - [字符串hash]
题目链接:传送门 描述 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围. 在本题中,我们希望使用快排.Hash与二分实现一个简单的 $O(n \log ...
随机推荐
- Web前端开发工程师的就业前景
Web前端开发工程师的就业前景 Web前端开发工程师是一个全新的职业,在IT行业真正受到重视的时间不超过5年.因此,大家越来越关心web前端工程师前景怎么样?web前端工程师就业如何?Web前端开发是 ...
- Redis内存管理(一)
Redis数据库的内存管理函数有关的文件为:zmalloc.h和zmalloc.c. Redis作者在编写内存管理模块时考虑到了查看系统内是否安装了TCMalloc或者Jemalloc模块,这两个是已 ...
- 蜥蜴(bzoj 1066)
Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平 ...
- Linear regression with multiple variables(多特征的线型回归)算法实例_梯度下降解法(Gradient DesentMulti)以及正规方程解法(Normal Equation)
,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, , ...
- Linear regression with one variable算法实例讲解(绘制图像,cost_Function ,Gradient Desent, 拟合曲线, 轮廓图绘制)_矩阵操作
%测试数据 'ex1data1.txt', 第一列为 population of City in 10,000s, 第二列为 Profit in $10,000s 1 6.1101,17.592 5. ...
- Mysql手册—基本规范与数据类型
第十章 本章主要介绍了一些语法规范,如 对于表,函数,字段,在Linux上大小写敏感,Windows和MacOS上却不敏感: Mysql是如何识别函数的及用户在定义自定义函数时命名要求:通过 ...
- SVM NG课件1
SVM NG课件1 2014年9月28日 16:39 一个二维空间点的示例 已使用 Microsoft OneNote 2013 创建.
- SQL Server 2014 BI新特性(一)五个关键点带你了解Excel下的Data Explorer
Data Explorer是即将发布的SQL Server 2014里的一个新特性,借助这个特性讲使企业中的自助式的商业智能变得更加的灵活,从而也降低了商业智能的门槛. 此文是在微软商业智能官方博客里 ...
- 攻城狮在路上(叁)Linux(二十七)--- 压缩与打包之常见的压缩命令
前面讲到,linux中的后缀名没有特殊的意义,一般是作为不同文件类型的标识而已.下面是与打包.压缩相关的后缀名介绍: *.z:compress程序压缩文件 *.gz:gzip程序压缩文件 *.bz2: ...
- 关于phpcms v9投票模块选项排序listorder设定问题
关于phpcms v9投票模块选项排序listorder设定问题修改,主要修改了三个文件三处地方. 主要修改三个文件: .phpcms\modules\vote\templates\vote_edit ...