【FFT+KMP】 URAL1996 Cipher Message 3

通道:http://acm.timus.ru/problem.aspx?space=1&num=1996

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

思路:前七位KMP,后面一位NlgN的hamming distance,将两个01串a , b。将b反转之后,求一次卷积,便可以得到a串中以i为起始位置,与b进行匹配有多少个位置同为1,那么接下来把a,b的值01反转一下,再求一次卷积,便可以得到a串中以i为起始位置,与b进行匹配有多少个位置同为0

代码:

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <vector>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 
  9 typedef long long ll;
 10 
 11 const int MAX_N = 300007; 
 12 const int MAX_M = 300007;
 13 const long double PI = acos(-1.0);
 14 
 15 struct Complex {
 16     long double r, i;
 17     Complex(long double _r, long double _i) {
 18         r = _r;
 19         i = _i;
 20     }
 21     Complex operator + (const Complex &c) {
 22         return Complex(c.r + r, c.i + i);
 23     }
 24     Complex operator - (const Complex &c) {
 25         return Complex(r - c.r, i - c.i);
 26     }
 27     Complex operator * (const Complex &c) {
 28         return Complex(c.r * r - c.i * i, c.r * i + c.i * r);
 29     }
 30     Complex operator / (const int &c) {
 31         return Complex(r / c, i / c);
 32     }
 33     Complex(){}
 34 };
 35 namespace FFT {
 36     int rev(int id, int len) {
 37         int ret = 0;
 38         for(int i = 0; (1 << i) < len; ++i) {
 39             ret <<= 1;
 40             if(id & (1 << i)) ret |= 1;
 41         }
 42         return ret;
 43     }
 44     Complex A[MAX_M << 3];
 45     void FFT(Complex *a, int len, int DFT) {
 46         for(int i = 0; i < len; ++i) A[rev(i, len)] = a[i];
 47         for(int s = 1; (1 << s) <= len; ++s) {
 48             int m = (1 << s);
 49             Complex wm = Complex(cos(PI * DFT * 2 / m), sin(PI * DFT * 2 / m));
 50             for(int k = 0; k < len; k += m) {
 51                 Complex w = Complex(1, 0);
 52                 for(int j = 0; j < (m >> 1); j++) {
 53                     Complex t = w * A[k + j + (m >> 1)];
 54                     Complex u = A[k + j];
 55                     A[k + j] = u + t;
 56                     A[k + j + (m >> 1)] = u - t;
 57                     w = w * wm;
 58                 }
 59             }
 60         }
 61         if(DFT == -1) for(int i = 0; i < len; ++i) A[i] = A[i] / len;
 62         for(int i = 0; i < len; i++) a[i] = A[i];
 63     }
 64 };
 65 
 66 int n, m;
 67 int a[MAX_N], b[MAX_N], p[MAX_N], e[MAX_N];
 68 vector<int> pos;
 69 Complex A[MAX_M << 3], B[MAX_M << 3]; 
 70 
 71 void getFail() {
 72     int j = 0;
 73     p[1] = 0;
 74     for (int i = 2; i <= m; ++i) {
 75         while (j > 0 && (b[j + 1] >> 1) != (b[i] >> 1)) j = p[j];
 76         if ((b[j + 1] >> 1) == (b[i] >> 1)) ++j;
 77         p[i] = j;
 78     }
 79 }
 80 
 81 void KMP() {
 82     getFail();
 83     int j = 0;
 84     for (int i = 1; i <= n; ++i) {
 85         while (j > 0 && (b[j + 1] >> 1) != (a[i] >> 1)) j = p[j];
 86         if ((b[j + 1] >> 1) == (a[i] >> 1)) ++j;
 87         if (j == m) {
 88             pos.push_back(i - m + 1);
 89             j = p[j];
 90         }
 91     }
 92 }
 93 
 94 int main() {
 95     while (2 == scanf("%d%d", &n, &m)) {
 96         for (int i = 1; i <= n; ++i) {
 97             char str[10]; scanf("%s", str); a[i] = 0;
 98             for (int j = 0; j < 8; ++j) a[i] <<= 1, a[i] |= str[j] - '0';
 99         }
100         for (int i = 1; i <= m; ++i) {
101             char str[10]; scanf("%s", str); b[i] = 0;
102             for (int j = 0; j < 8; ++j) b[i] <<= 1, b[i] |= str[j] - '0';
103         }
104         if (n < m) {
105             puts("No"); continue;
106         }
107         pos.clear();
108         KMP();
109         if (pos.size() == 0) {
110             puts("No"); continue;
111         }
112         int len = 1;
113         while (len <= n) len <<= 1; len <<= 1;
114         for (int i = 1; i <= n; ++i) A[i - 1] = Complex(a[i] & 1, 0);
115         for (int i = n; i < len; ++i) A[i] = Complex(0, 0);
116         for (int i = 1; i <= m; ++i) B[i - 1] = Complex(b[m - i + 1] & 1, 0);
117         for (int i = m; i < len; ++i) B[i] = Complex(0, 0);
118         FFT::FFT(A, len, 1); FFT::FFT(B, len, 1);
119         for (int i = 0; i < len; ++i) A[i] = A[i] * B[i];
120         FFT::FFT(A, len, -1);
121         memset(e, 0, sizeof e);
122         for (int i = 0; i < n - m + 1; ++i) e[i] = m - (int)(A[i + m - 1].r + 0.5);
123         
124         for (int i = 1; i <= n; ++i) A[i - 1] = Complex(a[i] & 1 ^ 1, 0);
125         for (int i = n; i < len; ++i) A[i] = Complex(0, 0);
126         for (int i = 1; i <= m; ++i) B[i - 1] = Complex(b[m - i + 1] & 1 ^ 1, 0);
127         for (int i = m; i < len; ++i) B[i] = Complex(0, 0);
128         FFT::FFT(A, len, 1); FFT::FFT(B, len, 1);
129         for (int i = 0; i < len; ++i) A[i] = A[i] * B[i];
130         FFT::FFT(A, len, -1);
131         for (int i = 0; i < n - m + 1; ++i) e[i] -= (int)(A[i + m - 1].r + 0.5);
132         int id = -1, step = 1e9 + 7;
133         puts("Yes");  
134         for(int i = 0, sz = pos.size(); i < sz; ++i) if(step > e[pos[i] - 1])  
135                 step = e[pos[i] - 1], id = pos[i];  
136         printf("%d %d\n", step, id);  
137     }
138     return 0;
139 }
View Code

 

posted @ 2015-07-24 16:07  mithrilhan  阅读(177)  评论(0编辑  收藏  举报