URAL 1996 Cipher Message 3 FFT + KMP
来源:互联网 发布:重庆优化公司哪家好 编辑:程序博客网 时间:2024/05/20 23:40
题目大意:
就是现在给出一幅画的存储代码为一组n个01串, 每个串的长度都是8, 现在有一串需要加密进去的01串, 长度为m个(n, m <= 250000)
现在可以将n个01串中的最后一个数字进行更改, 前7个01不能更改, 问是否能将这n个01串的末尾进行更改使得这个长度为m的加密消息出现在这个改动后的01串中
首先注意这题只有当前7位相同时才有可能改成相同, 那么可以先只看每个01串的前7位进行KMP匹配, 在O(n + m)的复杂度内找到所有可行的位置, 对于每个匹配位置需要进行的改动数量, 其实就是两个串之间的Hamming距离, 这个可以参见UVALive 4671的解法, 直接用FFT就可以在O(nlogn)的时间内得到, 那么这个问题也就解决了
代码如下:
Result : Accepted Memory : 29940 KB Time : 780 ms
/* * Author: Gatevin * Created Time: 2015/7/16 14:50:22 * File Name: URAL1996.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;const double PI = acos(-1.0);struct Complex{ double real, image; Complex(double _real, double _image) { real = _real; image = _image; } Complex(){}};Complex operator + (const Complex &c1, const Complex &c2){ return Complex(c1.real + c2.real, c1.image + c2.image);}Complex operator - (const Complex &c1, const Complex &c2){ return Complex(c1.real - c2.real, c1.image - c2.image);}Complex operator * (const Complex &c1, const Complex &c2){ return Complex(c1.real*c2.real - c1.image*c2.image, c1.real*c2.image + c1.image*c2.real);}int rev(int id, int len){ int ret = 0; for(int i = 0; (1 << i) < len; i++) { ret <<= 1; if(id & (1 << i)) ret |= 1; } return ret;}Complex A[1 << 19];void FFT(Complex *a, int len, int DFT){ for(int i = 0; i < len; i++) A[rev(i, len)] = a[i]; for(int s = 1; (1 << s) <= len; s++) { int m = (1 << s); Complex wm = Complex(cos(DFT*2*PI/m), sin(DFT*2*PI/m)); for(int k = 0; k < len; k += m) { Complex w = Complex(1, 0); for(int j = 0; j < (m >> 1); j++) { Complex t = w*A[k + j + (m >> 1)]; Complex u = A[k + j]; A[k + j] = u + t; A[k + j + (m >> 1)] = u - t; w = w*wm; } } } if(DFT == -1) for(int i = 0; i < len; i++) A[i].real /= len, A[i].image /= len; for(int i = 0; i < len; i++) a[i] = A[i]; return;}Complex N[1 << 19], M[1 << 19];int inN[250010], inM[250010];int next[250010];vector <int> pos;//表示匹配成功的开头位置int dif[250010];int n, m;void KMP(){ memset(next, 0, sizeof(next)); for(int i = 1; i < m; i++) { int j = i; while(j > 0) { j = next[j]; if((inM[i] >> 1) == (inM[j] >> 1)) { next[i + 1] = j + 1; break; } } } pos.clear(); for(int i = 0, j = 0; i < n; i++) { if((inM[j] >> 1) == (inN[i] >> 1)) { j++; } else { while(j > 0) { j = next[j]; if((inM[j] >> 1) == (inN[i] >> 1)) { j++; break; } } } if(j == m) pos.push_back(i - m + 1); }}char tmp[10];int main(){ while(~scanf("%d %d", &n, &m)) { for(int i = 0; i < n; i++) { scanf("%s", tmp); inN[i] = 0; for(int k = 0; k < 8; k++) { inN[i] <<= 1; if(tmp[k] == '1') inN[i] |= 1; } } for(int i = 0; i < m; i++) { scanf("%s", tmp); inM[i] = 0; for(int k = 0; k < 8; k++) { inM[i] <<= 1; if(tmp[k] == '1') inM[i] |= 1; } } if(n < m) { puts("No"); continue; } KMP(); if(pos.empty()) { puts("No"); continue; } //接下来FFT处理一下 int len = 1; while(len <= n) len <<= 1; len <<= 1; for(int i = 0; i < n - m + 1; i++) dif[i] = m; //先算出都是1的匹配位置 for(int i = 0; i < n; i++) N[i] = Complex(inN[i] & 1, 0); for(int i = n; i < len; i++) N[i] = Complex(0, 0); for(int i = 0; i < m; i++)//将M序列反向过来求两个串的Hamming距离(不同字符数) M[i] = Complex(inM[m - i - 1] & 1, 0); for(int i = m; i < len; i++) M[i] = Complex(0, 0); FFT(N, len, 1); FFT(M, len, 1); for(int i = 0; i < len; i++) N[i] = N[i] * M[i]; FFT(N, len, -1); for(int i = 0; i < n - m + 1; i++) dif[i] -= (int)(N[i + m - 1].real + 0.5); //接下来算出都是0的位置 for(int i = 0; i < n; i++) N[i] = Complex(1 - (inN[i] & 1), 0); for(int i = n; i < len; i++) N[i] = Complex(0, 0); for(int i = 0; i < m; i++) M[i] = Complex(1 - (inM[m - i - 1] & 1), 0); for(int i = m; i < len; i++) M[i] = Complex(0, 0); FFT(N, len, 1); FFT(M, len, 1); for(int i = 0; i < len; i++) N[i] = N[i] * M[i]; FFT(N, len, -1); for(int i = 0; i < n - m + 1; i++) dif[i] -= (int)(N[i + m - 1].real + 0.5); int minDif = 1e9 + 7, ansPos = -1; puts("Yes"); for(int i = 0, sz = pos.size(); i < sz; i++) if(minDif > dif[pos[i]]) minDif = dif[pos[i]], ansPos = pos[i]; printf("%d %d\n", minDif, ansPos + 1); } return 0;}
0 0
- URAL 1996 Cipher Message 3 (FFT + KMP)
- URAL 1996 Cipher Message 3 FFT + KMP
- URAL 1996 Cipher Message 3 (FFT + KMP)
- URAL 1996 Cipher Message 3 FFT KMP
- ural 1996. Cipher Message 3 KMP+FFT
- 【ural】1996. Cipher Message 3【FFT+KMP】
- ural 1654 Cipher Message
- URAL 1654 - Cipher Message
- ural 1654. Cipher Message
- Ural 1654 Cipher Message
- Ural 1654. Cipher Message
- Ural 1654. Cipher Message
- URAL 1654 Cipher Message
- ural 1654. Cipher Message
- URAL 1654 Cipher Message(栈)
- Ural 1706. Cipher Message 2 后缀数组
- URAL 1654. Cipher Message (STL stack)
- Cipher Message
- android webview响应web页面js
- The HealthKit Framework
- 关于Git的入门理解以及第二天实习收获
- cocos2d-x游戏开发(七)对象释放时机
- 实现相册的缩放图片功能
- URAL 1996 Cipher Message 3 FFT + KMP
- oracle 定时任务
- 强大的ViewDragHelper和ViewDragHelper的妙用 一
- merge javascript Object
- synergy 简易教程——多台主机共用一套鼠标键盘
- 修改全局状态栏颜色
- [腾讯]sizeof()和strlen()的区别
- cocos2d-x游戏开发(八)各类构造器
- Android 编译系统(NDK)