题目大意

给出两个\(01\)序列\(A\)和\(B\)

哈明距离定义为两个长度相同的序列中,有多少个对应位置上的数字不一样

"00111" 和 "10101"的距离为2

\(Q\)次询问,每次询问给出\(p_1,p_2,len\)

求\(a{p_1},a{p_1+1}...a_{p_1+len-1}\) 和 \(b_{p_1},b_{p_1+1}...b_{p_1+len-1}\)两个子串的哈明距离

注意:本题中的序列是从\(0\)开始编号的:\(a_0,a_1,...,a_{n-1}\)

\(1\leq |A|.|B|\leq 2*10^5,1\leq Q\leq 4*10^5\)

\(0 \leq p_1 \leq |a| - len\),\(0 \leq p_2 \leq |b| - len\)

分析

哈明距离可以转化成异或后有多少个\(1\)

考虑如何快速的比较两个字符串

我们先求出每个位置往后\(32\)位/\(64\)位的压位后的值

这样之后再暴力的复杂度就变成了\(\frac {len} {32}\)

我们再考虑对\(A\)串分块

每长度\(T\)分一块

预处理\(dif[i][j]\)表示\(A\)中第\(i\)块整个块 和 \(B\)中\(j\)开始的长度为\(T\)的串的哈明距离

\(O(\frac n T *m *\frac T {32})=O(\frac {n*m} {32})\)

对于询问

左右两边暴力扫\(O(T)\)

中间块内的用预处理直接求\(O(\frac n T)\)

算出来\(T=\sqrt n\)最优

同时T要是\(32\)/\(64\)的倍数

原题空间256M好像开不到\(n*\sqrt n\)的数组要调调参数

优化

块内的复杂度\(O(\frac {n*m} {32})\)小心脏承受不住

可以用FFT优化

s[i]==1的FFT数组中设为1,否则设为-1

将块中串反过来,卷积一波

求出来的值就是\(同-异\)

而块的大小为\(同+异\)

\(\frac {同+异-(同-异)} 2=异\)

这样就可以不用1算一次,0算一次再用总数减常数那么大了

结果越跑越慢

各种调参数到5000左右最快了

组合

如果两个算法合起来就完美了(越写越慢还好意思说)

注意

unsigned满位后左移一位可以看作把最高位扔掉后左移一位

bitset的count()是暴力

正确姿势:预处理1<<16内每个数有多少个1,分段算

FFT有负数用round()取整

solution(分块+压位)

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cctype>
  5. #include <cmath>
  6. #include <algorithm>
  7. #include <bitset>
  8. using namespace std;
  9. typedef unsigned long long ull;
  10. const int S=450;
  11. const int M=200003;
  12. const int N=1<<16;
  13. inline int rd(){
  14. int x=0;bool f=1;char c=getchar();
  15. for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
  16. for(;isdigit(c);c=getchar()) x=x*10+c-48;
  17. return f?x:-x;
  18. }
  19. char s[M];
  20. char t[M];
  21. int n,m,Q;
  22. int sn,MX;
  23. int cnt[N];
  24. ull aw[M],bw[M];
  25. int dif[S][M];
  26. int loc(int x){
  27. return x/sn+1;
  28. }
  29. int getL(int x){
  30. return (x-1)*sn;
  31. }
  32. int getR(int x){
  33. return x*sn-1;
  34. }
  35. int getP(int x){
  36. int L=getL(loc(x));
  37. return x-L+1;
  38. }
  39. int main(){
  40. int i,j,k,BL,BR,L,R,x,y,z,len;
  41. scanf("%s%s",s,t);
  42. n=strlen(s); m=strlen(t);
  43. sn=448; MX=loc(n);
  44. for(i=0;i<N;i++) cnt[i]=cnt[i>>1]+(i&1);
  45. for(i=0;i+63<n;i++)
  46. for(j=i;j<i+64;j++)
  47. aw[i]=aw[i]<<1|(s[j]=='1');
  48. for(i=0;i+63<m;i++)
  49. for(j=i;j<i+64;j++)
  50. bw[i]=bw[i]<<1|(t[j]=='1');
  51. int ful=N-1;
  52. for(i=1;i<=MX;i++){
  53. L=getL(i);
  54. if(L+sn-1>=n) break;
  55. for(j=0;j+sn-1<m;j++){
  56. x=L,y=j;
  57. for(k=7;k>0;k--){
  58. ull tp=aw[x]^bw[y];
  59. dif[i][j]+=cnt[tp&ful]+cnt[tp>>16&ful]+cnt[tp>>32&ful]+cnt[tp>>48];
  60. x+=64; y+=64;
  61. }
  62. }
  63. }
  64. Q=rd();
  65. int ans;
  66. while(Q--){
  67. ans=0;
  68. x=rd(),z=rd(),len=rd();
  69. y=x+len-1;
  70. BL=loc(x); BR=loc(y);
  71. if(BL+1>=BR){
  72. for(i=x;i<=y;i++) ans+=s[i]!=t[z+i-x];
  73. }
  74. else{
  75. if(getL(BL)!=x) BL++;
  76. if(getR(BR)!=y) BR--;
  77. L=getL(BL); R=getR(BR);
  78. for(i=BL;i<=BR;i++)
  79. ans+=dif[i][z+getL(i)-x];
  80. for(i=x;i<L;i++) ans+=s[i]!=t[z+i-x];
  81. for(i=y;i>R;i--) ans+=s[i]!=t[z+i-x];
  82. }
  83. printf("%d\n",ans);
  84. }
  85. return 0;
  86. }

solution(分块+FFT)

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cctype>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8. typedef double db;
  9. const int N=262144;
  10. const int S=207;
  11. const int M=200003;
  12. const db pi=acos(-1.0);
  13. inline int rd(){
  14. int x=0;bool f=1;char c=getchar();
  15. for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
  16. for(;isdigit(c);c=getchar()) x=x*10+c-48;
  17. return f?x:-x;
  18. }
  19. char s[M];
  20. char t[M];
  21. int rev[N];
  22. int n,m,Q;
  23. int sn,MX;
  24. struct CP{
  25. db x,i;
  26. CP(db xx=0.0,db ii=0.0){x=xx;i=ii;}
  27. }a[N],b[N],c[N];
  28. CP operator +(CP x,CP y){return CP(x.x+y.x,x.i+y.i);}
  29. CP operator -(CP x,CP y){return CP(x.x-y.x,x.i-y.i);}
  30. CP operator *(CP x,CP y){return CP(x.x*y.x-x.i*y.i,x.i*y.x+x.x*y.i);}
  31. void FFT(CP *a,int fl){
  32. int i,j,k;
  33. CP W,Wn,u,v;
  34. for(i=0;i<N;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
  35. for(i=2;i<=N;i<<=1){
  36. Wn=CP(cos(2*pi/i),fl*sin(2*pi/i));
  37. for(j=0;j<N;j+=i){
  38. W=CP(1,0);
  39. for(k=j;k<j+i/2;k++,W=W*Wn){
  40. u=a[k];
  41. v=a[k+i/2]*W;
  42. a[k]=u+v;
  43. a[k+i/2]=u-v;
  44. }
  45. }
  46. }
  47. if(fl==1) return ;
  48. for(i=0;i<N;i++) a[i].x/=N;
  49. }
  50. int dif[S][M];
  51. int loc(int x){
  52. return x/sn+1;
  53. }
  54. int getL(int x){
  55. return max(1,(x-1)*sn);
  56. }
  57. int getR(int x){
  58. return min(n,x*sn-1);
  59. }
  60. int getP(int x){
  61. int L=getL(loc(x));
  62. return x-L+1;
  63. }
  64. int main(){
  65. int i,j,BL,BR,L,R,x,y,z,len;
  66. scanf("%s%s",s+1,t+1);
  67. n=strlen(s+1); m=strlen(t+1);
  68. sn=5000; MX=loc(n);
  69. for(i=0;i<N;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?(N>>1):0);
  70. for(i=1;i<=m;i++) b[i]=(t[i]=='1')?1:-1;
  71. FFT(b,1);
  72. for(i=1;i<=MX;i++){
  73. L=getL(i);
  74. R=getR(i);
  75. for(j=0;j<N;j++) a[j]=CP();
  76. int tt=0;
  77. for(j=R;j>=L;j--) a[++tt]=(s[j]=='1')?1:-1;
  78. FFT(a,1);
  79. for(j=0;j<N;j++) c[j]=a[j]*b[j];
  80. FFT(c,-1);
  81. int sss=R-L+1;
  82. for(j=1;j<=m;j++) dif[i][j]=(sss-round(c[j+sss].x))/2;
  83. }
  84. Q=rd();
  85. int ans;
  86. while(Q--){
  87. ans=0;
  88. x=rd(),z=rd(),len=rd();
  89. x++;z++;//ÎÒ´Ó 1 ´æ
  90. y=x+len-1;
  91. BL=loc(x);BR=loc(y);
  92. if(BL+1>=BR){
  93. for(i=x;i<=y;i++) ans+=(s[i]!=t[z+i-x]);
  94. }
  95. else{
  96. if(getL(BL)!=x) BL++;
  97. if(getR(BR)!=y) BR--;
  98. L=getL(BL); R=getR(BR);
  99. for(i=x;i<L;i++) ans+=(s[i]!=t[z+i-x]);
  100. for(i=BL;i<=BR;i++)
  101. ans+=dif[i][z+getL(i)-x];
  102. for(i=y;i>R;i--) ans+=(s[i]!=t[z+i-x]);
  103. }
  104. printf("%d\n",ans);
  105. }
  106. return 0;
  107. }

cf 472G Design Tutorial: Increase the Constraints 分块+压位/FFT的更多相关文章

  1. 【CF472G】Design Tutorial: Increase the Constraints

    Description 给出两个01序列\(A\)和\(B\) 要求回答\(q\)个询问每次询问\(A\)和\(B\)中两个长度为\(len\)的子串的哈明距离 ​ 哈明距离的值即有多少个位置不相等 ...

  2. CF472G Increase the Constraints

    Increase the Constraints 定义两个等长的01字符串的汉明距离为它们字符不同的对应位置的个数. 给你两个01串S,T,现在有q个询问,每次指定S,T中两个定长的子串询问它们的汉明 ...

  3. Codeforces #270 D. Design Tutorial: Inverse the Problem

    http://codeforces.com/contest/472/problem/D D. Design Tutorial: Inverse the Problem time limit per t ...

  4. cf472D Design Tutorial: Inverse the Problem

    D. Design Tutorial: Inverse the Problem time limit per test 2 seconds memory limit per test 256 mega ...

  5. cf472C Design Tutorial: Make It Nondeterministic

    C. Design Tutorial: Make It Nondeterministic time limit per test 2 seconds memory limit per test 256 ...

  6. cf472B Design Tutorial: Learn from Life

    B. Design Tutorial: Learn from Life time limit per test 1 second memory limit per test 256 megabytes ...

  7. cf472A Design Tutorial: Learn from Math

    A. Design Tutorial: Learn from Math time limit per test 1 second memory limit per test 256 megabytes ...

  8. Codeforces Round #270--B. Design Tutorial: Learn from Life

    Design Tutorial: Learn from Life time limit per test 1 second memory limit per test 256 megabytes in ...

  9. Qsys 设计流程---Qsys System Design Tutorial

    Qsys 设计流程 ---Qsys System Design Tutorial 1.Avalon-MM Pipeline Bridge Avalon-MM Pipeline Bridge在slave ...

随机推荐

  1. Elastic Search Java Api 创建索引结构,添加索引

    创建TCP客户端 Client client = new TransportClient() .addTransportAddress(new InetSocketTransportAddress( ...

  2. Java Object类 instanceof关键字 练习:判断是否为同一人 集合按照人的年龄排序,如果年龄相同按名字的字母顺序升序 Comparator比较器

    package com.swift; public class Same_Person_Test { public static void main(String[] args) { /* * Obj ...

  3. 【转】PCA算法学习_1(OpenCV中PCA实现人脸降维)

    前言: PCA是大家经常用来减少数据集的维数,同时保留数据集中对方差贡献最大的特征来达到简化数据集的目的.本文通过使用PCA来提取人脸中的特征脸这个例子,来熟悉下在oepncv中怎样使用PCA这个类. ...

  4. 【SAM】bzoj5084: hashit

    做得心 力 憔 悴 Description 你有一个字符串S,一开始为空串,要求支持两种操作 在S后面加入字母C 删除S最后一个字母 问每次操作后S有多少个两两不同的连续子串 Input 一行一个字符 ...

  5. Unity基础-脚本的加载与编译顺序

    脚本的加载与编译顺序 C#是以Assembly(汇编集)为一个基本单元组织代码的,dll就是一个assembly,dll之间有加载以来顺序 Assets/*.dll Stamdard Assets/* ...

  6. ASP( VBScript ) 解析 JSON

    <script language="jscript" runat="server"> Array.prototype.get = function( ...

  7. LeetCode(292) Nim Game

    题目 You are playing the following Nim Game with your friend: There is a heap of stones on the table, ...

  8. 笔记-python-实用-程序运算时间计算

    方法1 import datetime starttime = datetime.datetime.now() #long running endtime = datetime.datetime.no ...

  9. Flask-用户角色及权限

    app/models.py class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=T ...

  10. selenium非常好的资料收集

    非常全的中文资料:http://qi-ling2006.iteye.com/ http://blog.csdn.net/qq744746842/article/details/49926917