传送门

解题思路

  因为要完全匹配,所以前七位必须保证相同,那么就可以把前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)的更多相关文章

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

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

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

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意 :给出两个串A , B,每个串是若干个byt ...

  3. URAL 1996 Cipher Message 3

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

  4. URAL 1654 Cipher Message 解题报告

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

  5. ural Cipher Message

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

  6. URAL1996 Cipher Message 3(KMP + FFT)

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

  7. Gym 100285G Cipher Message 3

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

  8. hdu 4300 Clairewd’s message(扩展kmp)

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

  9. hdu4300 Clairewd’s message 扩展KMP

    Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important ...

随机推荐

  1. 【JS】js引擎执行过程

    概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...

  2. SysTick功能总结

    一.初始化SysTick 按1ms来设置systick,也可以除以1000000.按1us来设置 SysTick_Config(SystemCoreClock / 1000); //SysTick开启 ...

  3. 关于自动化测试学习 selenium

    selenium学习路线 配置你的测试环境,真对你所学习语言,来配置你相应的selenium 测试环境.selenium 好比定义的语义---“问好”,假如你使用的是中文,为了表术问好,你的写法是“你 ...

  4. js中的关键子in的使用方法

    https://blog.csdn.net/jvid_sky/article/details/54967359

  5. 算法刷题笔记-stack-四则运算

    题目描述: 给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果.你需要给出所有可能的组合的结果.有效的运算符号包含 +, - 以及 * . 示例 1: 输入: &qu ...

  6. Vue环境搭建及第一个helloWorld

    Vue环境搭建及第一个helloWorld 一.环境搭建 1.node.js环境安装配置  https://www.cnblogs.com/liuqiyun/p/8133904.html 或者 htt ...

  7. Java对象toString()方法

    对象的字符串表示以可读格式包含有关对象状态的信息.Object类的toString()方法表示字符串中类的对象.Object类提供了toString()方法的默认实现. 它返回一个以下格式的字符串: ...

  8. shell编程2:数组的运用

    Shell 数组 定义数组 在Shell中,用括号来表示数组,数组元素用"空格"符号分割开.定义数组的一般形式为: name=(name1 name2 name3) 复制代码 还可 ...

  9. MySQL全面优化,速度飞起来!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 作者:惨绿少年 https://www.cnblogs.com/clsn/p/8214048.html 在进行MySQL的优 ...

  10. 23-python基础-python3-浅拷贝与深拷贝(1)

    1.可变和不可变数据类型. 列表是‘可变的’数据类型,它的值可以添加.删除或改变. 字符串是‘不可变的’,它不能被更改. (1)字符串 尝试对字符串中的一个字符重新赋值,将导致TypeError错误. ...