转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意 :给出两个串A , B,每个串是若干个byte,A串的每个byte的最后一个bit是可以修改的。问最少修改多少,使得B串是A的一个子串。

2013年NEERC的题。。。。。。。感觉[buaa]sd0061教我做这题。

NEERC是毛子题,但是这套题感觉除了题面很难读之外,并不是很难。。。

目前为止,J题貌似全队都没看题,E题还在WA中,其它题都没啥问题。

做法:前7位都是不能修改的,所以要完全匹配,那么先按前7位KMP一下,记录匹配的位置。之后就是统计以这些位置开始,需要修改多少位,然后 取最小值。

所以提取出最后一个bit,成了两个01串,统计hamming distance。

记得若干年前就和队友讨论过这个问题,不过当时不是01串,觉得不可在n * m之内解决,然后 就放弃了。结果这个01串是可以 在nlgn解决 的。吓傻。。

两个01串a , b。将b反转之后,求一次卷积,便可以得到a串中以i为起始位置,与b进行匹配有多少个位置同为1。

那么接下来把a,b的01反转一下,再求一次卷积,就可以得到原串中为多少个位置同为0。就得到了hamming距离。

卷积求的是c[i + j] = a[i] * b[j]。由于我们将b进行了反转,所以a串中以i为起始位置的。

c[i + m - 1] = a[i + 0] * b[m - 0 - 1] + a[i + 1] * b[m - 1 - 1] + …… a[i + j] * b[m - j - 1] + …… a[i + m - 1] * b[m - (m - 1) - 1]。

如果a , b中同为1,乘积为1,否则为0,这样就统计出了有多少位同为1了。吓傻。。。太神了。

预处理出这个之后,再枚举之前KMP所得到的匹配位置 就可以了。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <vector>
  6. #include <algorithm>
  7. #include <queue>
  8. #include <set>
  9. using namespace std;
  10. typedef long long LL;
  11. typedef pair<int , int> pii;
  12. const int N = 1000005;
  13. //FFT copy from kuangbin
  14. const double pi = acos (-1.0);
  15. // Complex z = a + b * i
  16. struct Complex {
  17. double a, b;
  18. Complex(double _a=0.0,double _b=0.0):a(_a),b(_b){}
  19. Complex operator + (const Complex &c) const {
  20. return Complex(a + c.a , b + c.b);
  21. }
  22. Complex operator - (const Complex &c) const {
  23. return Complex(a - c.a , b - c.b);
  24. }
  25. Complex operator * (const Complex &c) const {
  26. return Complex(a * c.a - b * c.b , a * c.b + b * c.a);
  27. }
  28. };
  29. //len = 2 ^ k
  30. inline void change (Complex y[] , int len) {
  31. for (int i = 1 , j = len / 2 ; i < len -1 ; i ++) {
  32. if (i < j) swap(y[i] , y[j]);
  33. int k = len / 2;
  34. while (j >= k) {
  35. j -= k;
  36. k /= 2;
  37. }
  38. if(j < k) j += k;
  39. }
  40. }
  41. // FFT
  42. // len = 2 ^ k
  43. // on = 1 DFT on = -1 IDFT
  44. inline void FFT (Complex y[], int len , int on) {
  45. change (y , len);
  46. for (int h = 2 ; h <= len ; h <<= 1) {
  47. Complex wn(cos (-on * 2 * pi / h), sin (-on * 2 * pi / h));
  48. for (int j = 0 ; j < len ; j += h) {
  49. Complex w(1 , 0);
  50. for (int k = j ; k < j + h / 2 ; k ++) {
  51. Complex u = y[k];
  52. Complex t = w * y [k + h / 2];
  53. y[k] = u + t;
  54. y[k + h / 2] = u - t;
  55. w = w * wn;
  56. }
  57. }
  58. }
  59. if (on == -1) {
  60. for (int i = 0 ; i < len ; i ++) {
  61. y[i].a /= len;
  62. }
  63. }
  64. }
  65. int n , m , a[N] , b[N];
  66. int c[N] , d[N] , next[N] , p[N];
  67. char str[10];
  68. void get_next (int *a , int l) {
  69. int i = 0 , j = -1;
  70. next[i] = j;
  71. while (i < l) {
  72. if (j == -1 || a[i] == a[j]) {
  73. i ++; j ++;
  74. next[i] = j;
  75. }
  76. else j = next[j];
  77. }
  78. }
  79. int pos[N] , cnt;
  80. void match (int *a , int la , int *b , int lb) {
  81. int i = 0 , j = 0;
  82. while (i < la) {
  83. if (j == -1 || a[i] == b[j]) {
  84. i ++;j ++;
  85. if (j == lb) {
  86. pos[cnt ++] = i - lb;
  87. j = next[j];
  88. }
  89. }
  90. else j = next[j];
  91. }
  92. }
  93. Complex x1[N] , x2[N];
  94. void gao (int *a , int *b) {
  95. int len = max (n , m);
  96. int l = 1;
  97. while (l < len * 2) l <<= 1;
  98. for (int i = 0 ; i < n ; i ++)
  99. x1[i] = Complex (a[i] , 0);
  100. for (int i = n ; i < l ; i ++)
  101. x1[i] = Complex (0 , 0);
  102. FFT (x1 , l , 1);
  103. for (int i = 0 ; i < m ; i ++)
  104. x2[i] = Complex (b[i] , 0);
  105. for (int i = m ; i < l ; i ++)
  106. x2[i] = Complex (0 , 0);
  107. FFT (x2 , l , 1);
  108. for (int i = 0 ; i < l ; i ++)
  109. x1[i] = x1[i] * x2[i];
  110. FFT (x1 , l , -1);
  111. for (int i = 0 ; i <= n - m ; i ++) {
  112. p[i] += (int)(x1[i + m - 1].a + 0.5);
  113. }
  114. }
  115. int main () {
  116. while (scanf ("%d %d" , &n , &m) != EOF) {
  117. for (int i = 0 ; i < n ; i ++) {
  118. scanf ("%s" , str);
  119. a[i] = 0;
  120. for (int j = 0 ; j < 7 ; j ++)
  121. a[i] = a[i] * 2 + str[j] - '0';
  122. c[i] = str[7] - '0';
  123. }
  124. for (int i = 0 ; i < m ; i ++) {
  125. scanf ("%s" , str);
  126. b[i] = 0;
  127. for (int j = 0 ; j < 7 ; j ++)
  128. b[i] = b[i] * 2 + str[j] - '0';
  129. d[m - i - 1] = str[7] - '0';
  130. }
  131. get_next (b , m);
  132. cnt = 0;
  133. match (a , n , b , m);
  134. if (cnt == 0) puts ("No");
  135. else {
  136. memset (p , 0 , sizeof(p));
  137. puts ("Yes");
  138. gao (c , d);
  139. for (int i = 0 ; i < n ; i ++)
  140. c[i] = c[i] ^ 1;
  141. for (int i = 0 ; i < m ; i ++)
  142. d[i] = d[i] ^ 1;
  143. gao (c , d);
  144. int ans = m + 1 , idx = -1;
  145. for (int i = 0 ; i < cnt ; i ++) {
  146. if (m - p[pos[i]] < ans)
  147. ans = m - p[pos[i]] , idx = pos[i];
  148. }
  149. printf ("%d %d\n" , ans , idx + 1);
  150. }
  151. }
  152. return 0;
  153. }

URAL 1996 Cipher Message 3 (FFT + KMP)的更多相关文章

  1. URAL 1996 Cipher Message 3

    题目 神题. 记得当初DYF和HZA讲过一个FFT+KMP的题目,一直觉得很神,从来没去做. 没有真正理解FFT的卷积. 首先考虑暴力. 只考虑前7位 KMP 找出所有 B 串可以匹配 A 串的位置. ...

  2. URAL 1996. Cipher Message 3(KMP+fft)

    传送门 解题思路 因为要完全匹配,所以前七位必须保证相同,那么就可以把前7位提出来做一遍\(kmp\)匹配,最后的答案一定在这些位置里.考虑最后一位,可以把最后一位单独取出来,要计算的是最后一位相同的 ...

  3. Ural 1996 Cipher Message 3 (生成函数+FFT)

    题面传送门 题目大意:给你两个$01$串$a$和$b$,每$8$个字符为$1$组,每组的最后一个字符可以在$01$之间转换,求$b$成为$a$的一个子串所需的最少转换次数,以及此时是从哪开始匹配的. ...

  4. URAL1996 Cipher Message 3(KMP + FFT)

    题目 Source http://acm.timus.ru/problem.aspx?space=1&num=1996 Description Emperor Palpatine has be ...

  5. URAL 1654 Cipher Message 解题报告

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1654 题意:简单的理解就是,把一个序列中相邻的且是偶数个相同的字符删除,奇数个的话就只保 ...

  6. ural Cipher Message

    Cipher Message Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Desc ...

  7. Gym 100285G Cipher Message 3

    题意 给\(N,M(N,M \le 250000)\)的两个由8位二进制表示的两个序列,允许改变每个数字的第8位的数值(即0→1,1→0),求改变最少次数使得长为\(M\)的序列为长为\(N\)的连续 ...

  8. 北京集训TEST16——图片加密(fft+kmp)

    题目: Description CJB天天要跟妹子聊天,可是他对微信的加密算法表示担心:“微信这种加密算法,早就过时了,我发明的加密算法早已风靡全球,安全性天下第一!” CJB是这样加密的:设CJB想 ...

  9. HDU4300 Clairewd’s message(拓展kmp)

    Problem Description Clairewd is a member of FBI. After several years concealing in BUPT, she interce ...

随机推荐

  1. 【升级至sql 2012】sqlserver mdf向上兼容附加数据库(无法打开数据库 'xxxxx' 版本 611。请将该数据库升级为最新版本。)

    sqlserver mdf向上兼容附加数据库(无法打开数据库 'xxxxx' 版本 611.请将该数据库升级为最新版本.) 最近工作中有一个sqlserver2005版本的mdf文件,还没有log文件 ...

  2. 列名 'Discriminator' 无效 解决方案

     {"列名 'Discriminator' 无效.\r\n列名 'Discriminator' 无效.\r\n列名 'Discriminator' 无效.\r\n列名 'FileUrl' 无 ...

  3. jquery使用js的一些疼处

    使用javascript的一些疼处 书写繁琐,代码量大 代码复杂 动画效果,很难实现.使用定时器 各种操作和处理 HTML <button id="btn">按钮< ...

  4. 并发包学习(一)-Atomic包小记

    此篇是J.U.C学习的第一篇Atomic包相关的内容,希望此篇总结能对自己的基础有所提升.本文总结来源自<Java并发编程的艺术>第七章并配以自己的实践理解.如有错误还请指正. 一.案例分 ...

  5. ggplot map

    ggplot {ggplot2} R Documentation Create a new ggplot Description ggplot() initializes a ggplot objec ...

  6. [think\exception\ErrorException] glob() has been disabled for security reasons

    今天同事开发 出现了这个错误 [think\exception\ErrorException] glob() has been disabled for security reasons 打开php. ...

  7. MPI 计时器函数 MPI_Wtime()

    ▶ 计时器函数 MPI_Wtime() 以及头文件 timer.h 中的宏函数 GET_TIME(),类似 time.h 中函数 clock() 的用法.注意 函数 clock() 记录的是CPU时间 ...

  8. 如何连接并处理 sdf 数据库文件(便捷数据库处理)

    如何连接并处理 sdf 数据库文件 SqlCeConnection cc = new SqlCeConnection();        DataTable dt = new DataTable(); ...

  9. C++如何实现DNS域名解析<转>

    C++如何实现DNS域名解析 这片文章介绍了C++如何实现DNS域名解析,还有对相关技术的介绍,代码很详细,需要的朋友可以参考下   一.概述 现在来搞定DNS域名解析,其实这是前面一篇文章C++实现 ...

  10. oracle ROW_NUMBER用法

    Oracle中row_number().rank().dense_rank() 的区别 row_number的用途非常广泛,排序最好用它,它会为查询出来的每一行记录生成一个序号,依次排序且不会重复 使 ...