URAL1966 Cipher Message 3
题解:
能看出来的是,每一组数只能改最后一位,所以前$7$位动不了。
所以$KMP$跑一跑。
重点在于最后一位怎么搞。
如果$KMP$跑完了还没找到合适的位置,直接$puts("No")$就好了。
剩下个匹配问题。
(要不是数据范围拦着我我都想建图跑费用流了)
这个匹配可以用$FFT$求。
$FFT$不是求$\sum(a[i]*b[j-i])$的吗?怎么求字符串匹配?
其实我们只想要最后多项式中某一位上的值,所以$b[j-i]$和$b[i]$没有区别,反转数组就好了。
我们要求的是需要多少个$0$变成$1$,以及多少个$1$变成$0$。
所以$FFT$求两遍卷积,第一次$a[i]=[s1[i]==0],b[i]=[s2[i]==1]$,注意这里的$b$还没有反转。
第二次反过来就可以了。
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
const int N = ;
const ull seed = ;
const double Pi = acos(-1.0);
template<typename T>
inline void read(T&x)
{
T f = ,c = ;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){c=c*+ch-'';ch=getchar();}
x = f*c;
}
struct cp
{
double x,y;
cp(){}
cp(double x,double y):x(x),y(y){}
cp operator + (const cp&a)const{return cp(x+a.x,y+a.y);}
cp operator - (const cp&a)const{return cp(x-a.x,y-a.y);}
cp operator * (const cp&a)const{return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
};
int to[*N],lim=,l;
void fft(cp *a,int len,int k)
{
for(int i=;i<len;i++)
if(i<to[i])swap(a[i],a[to[i]]);
for(int i=;i<len;i<<=)
{
cp w0(cos(Pi/i),k*sin(Pi/i));
for(int j=;j<len;j+=(i<<))
{
cp w(,);
for(int o=;o<i;o++,w=w*w0)
{
cp w1 = a[j+o],w2 = a[j+o+i]*w;
a[j+o] = w1+w2;
a[j+o+i] = w1-w2;
}
}
}
if(k==-)
for(int i=;i<len;i++)
a[i].x/=len;
}
void rd(int n,int *a1,int *a2)
{
for(int x,i=;i<=n;i++)
{
read(x);
a1[i] = x%;
a2[i] = x/;
}
}
int n,m,a[][N],b[][N];
bool vis[N];
int ans[N];
cp c1[*N],c2[*N],c3[*N];
int nxt[N];
void get_nxt(int *a,int len)
{
int i = ,j = ;
while(i<=len)
{
if(!j||a[i]==a[j])
{
i++,j++;
nxt[i] = j;
}else j = nxt[j];
}
}
int kmp(int *a,int la,int *b,int lb)
{
int ret = ;
int i = ,j = ;
while(i<=la)
{
if(a[i]==b[j]||j==)
{
i++,j++;
if(j==lb+)
{
vis[i-]=;
j = nxt[j];
ret = ;
}
}else j=nxt[j];
}
return ret;
}
void work()
{
fft(c1,lim,),fft(c2,lim,);
for(int i=;i<lim;i++)c3[i]=c1[i]*c2[i];
fft(c3,lim,-);
}
void init()
{
memset(a,,sizeof(a));
memset(b,,sizeof(b));
memset(ans,,sizeof(ans));
memset(vis,,sizeof(vis));
lim=,l=;
}
int main()
{
// freopen("tt.in","r",stdin);
while(scanf("%d%d",&n,&m)>)
{
init();
rd(n,a[],a[]),rd(m,b[],b[]);
get_nxt(b[],m);
if(!kmp(a[],n,b[],m))
{
puts("No");
continue;
}
puts("Yes");
while(lim<*(n+m))lim<<=,l++;
for(int i=;i<lim;i++)to[i]=((to[i>>]>>)|((i&)<<(l-)));
for(int i=;i<lim;i++)c1[i]=c2[i]=cp(,);
for(int i=;i<n;i++)c1[i].x=(a[][i+]==);
for(int i=;i<m;i++)c2[i].x=(b[][m-i]==);
work();
for(int i=;i<n;i++)ans[i+]=(int)(c3[i].x+0.5);
for(int i=;i<lim;i++)c1[i]=c2[i]=cp(,);
for(int i=;i<n;i++)c1[i].x=(a[][i+]==);
for(int i=;i<m;i++)c2[i].x=(b[][m-i]==);
work();
for(int i=;i<n;i++)ans[i+]+=(int)(c3[i].x+0.5);
int mn = N,pos=;
for(int i=m;i<=n;i++)
if(vis[i]&&ans[i]<mn)
{
mn = ans[i];
pos = i-m+;
}
printf("%d %d\n",mn,pos);
}
return ;
}
URAL1966 Cipher Message 3的更多相关文章
- 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 ...
- URAL 1654 Cipher Message 解题报告
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1654 题意:简单的理解就是,把一个序列中相邻的且是偶数个相同的字符删除,奇数个的话就只保 ...
- Gym 100285G Cipher Message 3
题意 给\(N,M(N,M \le 250000)\)的两个由8位二进制表示的两个序列,允许改变每个数字的第8位的数值(即0→1,1→0),求改变最少次数使得长为\(M\)的序列为长为\(N\)的连续 ...
- Cipher Message
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=34121#problem/C // File Name: c.cpp // Author: ...
- 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 1996 Cipher Message 3 (生成函数+FFT)
题面传送门 题目大意:给你两个$01$串$a$和$b$,每$8$个字符为$1$组,每组的最后一个字符可以在$01$之间转换,求$b$成为$a$的一个子串所需的最少转换次数,以及此时是从哪开始匹配的. ...
- URAL 1996. Cipher Message 3(KMP+fft)
传送门 解题思路 因为要完全匹配,所以前七位必须保证相同,那么就可以把前7位提出来做一遍\(kmp\)匹配,最后的答案一定在这些位置里.考虑最后一位,可以把最后一位单独取出来,要计算的是最后一位相同的 ...
随机推荐
- 洛谷 - P1309 - 瑞士轮 - 归并排序
https://www.luogu.org/problemnew/show/P1309 一开始写的直接快排没想到真的TLE了. 想到每次比赛每个人前移的量不会很多,但是不知从哪里开始优化. 搜索一下原 ...
- 51nod 1225:余数之和
传送门 题意 略 分析 \(\sum_i^n(n\%i)=\sum_i^n(n-i*n/i)=n^2-\sum_i^ni*n/i\) \(=\sum r\sum_i^ni[n/i==r]\) 可以证明 ...
- python __builtins__ bytearray类 (7)
7.'bytearray', 返回一个新字节数组.这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256. class bytearray(object) | byte ...
- The local variable fruit may not have been initialized 错误
eclipse错误提示如图: 错误代码如图: 首先这错误的翻译是:局部变量"水果"尚未初始化,所以对象该如何初始化呢,我百度之后找到了答案,修改过后如下图所示. 这个错误的问题所在 ...
- python 中site-packages 和 dist-packages的区别
dist-packages is a Debian-specific convention that is also present in its derivatives, like Ubuntu. ...
- Linux中查看端口占用情况及结束相应进程
1.查看某端口占用情况lsof -i :端口号 例如:lsof -i :81 显示如下信息: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME ja ...
- 力荐!35 个最好用的 Vue 开源库!
无论是开发新手还是经验丰富的老手,我们都喜欢开源软件包.对于开发者来说,如果没有这些开源软件包,很难想象我们的生活会变得多么疲惫不堪,而且靠咖啡度日也会成为家常便饭.所幸的是,随着 Vue.js 和 ...
- 洛谷 P2023 [AHOI2009]维护序列 || 线段树加法和乘法运算
原理倒是非常简单.设原数为x,加法的lazytag为b,乘法的lazytag为a,操作数为c,那么原式为ax+b,乘上c后(ax+b)c=(ac)*x+b*c,加上c后(ax+b)+c=ax+(b+c ...
- 二分查找 2015百度之星初赛1 HDOJ 5246 超级赛亚ACMer
题目传送门 /* 二分找到不大于m的最大的数,记做p,只要a[p] + k <= a[p+1]就继续 注意:特判一下当没有比m小的数的情况:) */ #include <cstdio> ...
- [转]Intellij Idea自动添加注释的方法
Intellij Idea自动添加注释的方法 阿历Ali 关注 2017.08.20 21:22* 字数 914 阅读 2741评论 0喜欢 6 程序媛阿历终于要写第一篇关于开发的文章了!!! 阿历用 ...