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 ...
随机推荐
- 模拟赛1103d1
取模(mod) [题目描述] 有一个整数a和n个整数b_1, -, b_n.在这些数中选出若干个数并重新排列,得到c_1,-, c_r.我们想保证a mod c_1 mod c_2 mod - mod ...
- SQL Server多表多列更新
student表: lag表: 要求将student表stu_id列为1的stu_nick列和stu_phont列的数据更新为lag表的lag_nick列和lag_phone列. SQL语句: upd ...
- js判断是否为ie6以外的浏览器,若是,则调用相应脚本
if(navigator.userAgent.indexOf("MSIE 6.0") < 0) { //相应JavaScript脚本}
- C#中的变量及命名规则
变量: 1.作用 :可以让我们在计算机中存储数据 2.语法:变量类型 变量名=赋值: 3.常用的数据类型: int 整数类型 取值范围:最大2147483647;最小-214748364 ...
- 从xml中构建sqlSessionFactory
String resource = "org/mybatis/example/Configuration.xml"; Reader reader = Resources.getRe ...
- React Native实例之房产搜索APP
React Native 开发越来越火了,web app也是未来的潮流, 现在react native已经可以完成一些最基本的功能. 通过开发一些简单的应用, 可以更加熟练的掌握 RN 的知识. 在学 ...
- hdu 2027统计元音
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2027 思路:主要考察gets()函数用法,能够接受输入的空格,如果用%s或是cin>>st ...
- Mac系统下使用VirtualBox虚拟机安装win7--第一步 安装vbox虚拟机
Mac系统下使用VirtualBox虚拟机安装win7操作步骤: 第一步 安装vbox虚拟机 1.先下载vbox,下载地址:: https://www.virtualbox.org/wiki/Down ...
- php 用户登录验证
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- samba 最简单配置 共享
[root@GitLab ~]# cat /etc/samba/smb.conf [global] workgroup = WORKGROUP server string = David Samba ...