URAL 1996. Cipher Message 3(KMP+fft)
解题思路
因为要完全匹配,所以前七位必须保证相同,那么就可以把前7位提出来做一遍\(kmp\)匹配,最后的答案一定在这些位置里。考虑最后一位,可以把最后一位单独取出来,要计算的是最后一位相同的个数,那么就可以做两次\(fft\)得到\(haming dis\)。先把\(b\)翻转,然后做一次,得到的是全为\(1\)的个数,再把\(a,b\)取反做一次,得到的是全为\(0\)的个数,然后扫一遍\(kmp\)后的匹配位置,取个最小值。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int MAXN = 1000005;
const double Pi = acos(-1);
int a[MAXN],b[MAXN],pos[MAXN],p[MAXN],rev[MAXN],id,n,m;
int nxt[MAXN],cnt,limit=1,c[MAXN],d[MAXN],ans=1e9;
struct Complex{
double x,y;
Complex(double _x=0,double _y=0){x=_x;y=_y;}
}f[MAXN],g[MAXN];
Complex operator+(Complex A,Complex B){return Complex(A.x+B.x,A.y+B.y);}
Complex operator-(Complex A,Complex B){return Complex(A.x-B.x,A.y-B.y);}
Complex operator*(Complex A,Complex B){return Complex(A.x*B.x-A.y*B.y,A.x*B.y+A.y*B.x);}
void fft(Complex *f,int type){
for(int i=0;i<limit;i++) if(i<rev[i]) swap(f[i],f[rev[i]]);
Complex Wn,w,tmp;int len;
for(int i=2;i<=limit;i<<=1){
len=i>>1;Wn=Complex(cos(Pi/len),type*sin(Pi/len));
for(int j=0;j<limit;j+=i){
w=Complex(1,0);
for(int k=j;k<j+len;k++){
tmp=w*f[k+len];f[k+len]=f[k]-tmp;
f[k]=f[k]+tmp;w=w*Wn;
}
}
}
}
inline void get_nxt(){
for(int i=2,j=0;i<=m;i++){
while(j>0 && b[i]!=b[j+1]) j=nxt[j];
if(b[i]==b[j+1]) j++;
nxt[i]=j;
}
}
inline void get_match(){
for(int i=1,j=0;i<=n;i++){
while(j>0 && a[i]!=b[j+1]) j=nxt[j];
if(a[i]==b[j+1]) j++;
if(j==m) pos[++cnt]=i-m+1,j=nxt[j];
}
}
inline void get_init(){
while(limit<=n+m) limit<<=1;
for(int i=0;i<limit;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?limit>>1:0);
}
inline void get_ans(){
for(int i=0;i<n;i++) f[i].x=c[i],f[i].y=0;
for(int i=0;i<m;i++) g[i].x=d[i],g[i].y=0;
for(int i=n;i<limit;i++) f[i].x=f[i].y=0;
for(int i=m;i<limit;i++) g[i].x=g[i].y=0;
fft(f,1);fft(g,1);
for(int i=0;i<limit;i++) f[i]=f[i]*g[i];
fft(f,-1);
for(int i=0;i<=n-m;i++) p[i]+=(int)(f[i+m-1].x/limit+0.5);
}
int main(){
scanf("%d%d",&n,&m);char s[10];
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=7;j++)
a[i]=(a[i]<<1)+(s[j]-'0');
c[i-1]=s[8]-'0';
}
for(int i=1;i<=m;i++){
scanf("%s",s+1);
for(int j=1;j<=7;j++)
b[i]=(b[i]<<1)+(s[j]-'0');
d[m-i]=s[8]-'0';
}
get_nxt();get_match();
if(!cnt) puts("No");
else{
puts("Yes");
get_init();get_ans();
for(int i=0;i<n;i++) c[i]^=1;
for(int i=0;i<m;i++) d[i]^=1;
get_ans();
for(int i=1;i<=cnt;i++)
if(m-p[pos[i]-1]<ans) {
ans=m-p[pos[i]-1];
id=pos[i];
}
printf("%d %d",ans,id);
}
return 0;
}
URAL 1996. Cipher Message 3(KMP+fft)的更多相关文章
- Ural 1996 Cipher Message 3 (生成函数+FFT)
题面传送门 题目大意:给你两个$01$串$a$和$b$,每$8$个字符为$1$组,每组的最后一个字符可以在$01$之间转换,求$b$成为$a$的一个子串所需的最少转换次数,以及此时是从哪开始匹配的. ...
- URAL 1996 Cipher Message 3 (FFT + KMP)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意 :给出两个串A , B,每个串是若干个byt ...
- URAL 1996 Cipher Message 3
题目 神题. 记得当初DYF和HZA讲过一个FFT+KMP的题目,一直觉得很神,从来没去做. 没有真正理解FFT的卷积. 首先考虑暴力. 只考虑前7位 KMP 找出所有 B 串可以匹配 A 串的位置. ...
- URAL 1654 Cipher Message 解题报告
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1654 题意:简单的理解就是,把一个序列中相邻的且是偶数个相同的字符删除,奇数个的话就只保 ...
- ural Cipher Message
Cipher Message Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Desc ...
- URAL1996 Cipher Message 3(KMP + FFT)
题目 Source http://acm.timus.ru/problem.aspx?space=1&num=1996 Description Emperor Palpatine has be ...
- Gym 100285G Cipher Message 3
题意 给\(N,M(N,M \le 250000)\)的两个由8位二进制表示的两个序列,允许改变每个数字的第8位的数值(即0→1,1→0),求改变最少次数使得长为\(M\)的序列为长为\(N\)的连续 ...
- hdu 4300 Clairewd’s message(扩展kmp)
Problem Description Clairewd is a member of FBI. After several years concealing in BUPT, she interce ...
- hdu4300 Clairewd’s message 扩展KMP
Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important ...
随机推荐
- org.zkoss.zul.Filedownload.java 源码
/* Filedownload.java Purpose: Description: History: Mon Apr 16 09:29:44 2007, Created by tomyeh Copy ...
- 二叉树入门(洛谷P1305)
题目描述 输入一串完全二叉树,用遍历前序打出. 输入输出格式 输入格式: 第一行为二叉树的节点数n. 后面n行,每一个字母为节点,后两个字母分别为其左右儿子. 空节点用*表示 输出格式: 前序排列的完 ...
- IP地址的定义和划分
IP地址分类: IP地址根据首首字节开始位可以分为5大类: 分类 首字节开始位 首字节数字范围 ...
- MySQL 小数处理函数 round 和 floor
一. 在mysql中,round函数用于数据的四舍五入,它有两种形式: 1.round(x,d) ,x指要处理的数,d是指保留几位小数 这里有个值得注意的地方是,d可以是负数,这时是指定小数点左边的 ...
- MySQL-存储过程动态执行sql
存储过程动态执行 sql --存储过程名和参数,参数中in表示传入参数,out标示传出参数,inout表示传入传出参数 create procedure p_procedurecode(in sumd ...
- Java 实例 - 状态监测
以下实例演示了如何通过继承 Thread 类并使用 currentThread.getName() 方法来监测线程的状态: Main.java 文件 1 2 3 4 5 6 7 8 9 10 11 1 ...
- VC的小工具查询exe的依赖
查看程序或动态库所依赖的动态库 dumpbin /dependents abc.exe 查看动态库的输出函数 dumpbin /exports abc.dll
- linux python3换pip 源
linux下python3 pip 安装模块 # python3 -m pip install pymysql 1)检查pip.conf文件是否存在 >> cd ~ > ...
- Python科学计算:用NumPy快速处理数据
创建数组 import numpy as np a=np.array([1,2,3]) b=np.array([[1,2,3],[4,5,6],[7,8,9]]) b[1,1]=10 print(a. ...
- Oracle查看有锁进程,删除锁
查看锁表进程SQL语句1: select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao ...