日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

弱省互测#2 t3

發布時間:2024/4/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 弱省互测#2 t3 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意

給出\(n\)個01字節和\(m\)個01字節,要求用后者去匹配前者,兩個串能匹配當且僅當除了每個字節末位不同,其他位都要相同。問匹配后者至少有多少個末位不同。(\(1 \le m \le n \le 2.5 \times 10^5\)

分析

首先我們可以用kmp計算出能匹配的位置,然后單獨考慮末位不同的情況。

題解

我們將末尾的位提取出來,則考慮\(n\)\(01\)位和\(m\)\(01\)位。對于模板串的\(01\)位,我們需要計算以這個位置結束與匹配串位相同的數目,發現其實我們將匹配串反轉,然后就是卷積!于是我們就可以用fft做了。

#include <bits/stdc++.h> using namespace std; const double pi=acos(-1); const int N=2.5e5+10, nS=N*8, Lim=600006; int lenn, lenm, lena, lenb, got[Lim], rev[Lim]; char s1[nS], s2[nS], sa[nS], sb[nS]; vector<int> pos; void getkmp() {static int p[nS];memset(p, -1, sizeof(int)*lena);int j=-1;for(int i=1; i<lena; ++i) {while(j!=-1 && sa[j+1]!=sa[i]) j=p[j];if(sa[j+1]==sa[i]) ++j;p[i]=j;}j=-1;for(int i=0; i<lena; ++i) {while(j!=-1 && sb[j+1]!=sa[i]) j=p[j];if(sb[j+1]==sa[i]) ++j;if(j==lenb-1) {int t=i-j;if(t%7==0) {pos.push_back(t/7);}}} } struct icp {double r, i;icp(double _r=0, double _i=0) : r(_r), i(_i) { } }; icp operator + (const icp &a, const icp &b) { return icp(a.r+b.r, a.i+b.i); } icp operator - (const icp &a, const icp &b) { return icp(a.r-b.r, a.i-b.i); } icp operator * (const icp &a, const icp &b) { return icp(a.r*b.r-a.i*b.i, a.r*b.i+a.i*b.r); } int getlen(int n) {int len=1, bl=-1;for(; len<n; len<<=1, ++bl);for(int i=0; i<len; ++i) {rev[i]=(rev[i>>1]>>1)|((i&1)<<bl);}return len; } void fft(icp *a, int n, int flag) {for(int i=0; i<n; ++i) {if(rev[i]<i) {swap(a[rev[i]], a[i]);}}for(int m=2; m<=n; m<<=1) {icp wn(cos(pi*2/m), sin(pi*2/m)*flag);for(int i=0, mid=m>>1; i<n; i+=m) {icp w(1);for(int j=0; j<mid; ++j) {icp u=a[i+j], v=a[i+j+mid]*w;a[i+j]=u+v;a[i+j+mid]=u-v;w=w*wn;}}}if(flag==-1) {for(int i=0; i<n; ++i) {a[i].r/=n;}} } void dofft(char *A, char *B, int *C, int n, int m) { #define CLR(a) for(int i=0; i<len; ++i) a[i].r=a[i].i=0;static icp a[Lim], b[Lim], c[Lim];int len=getlen(n+m-1);CLR(a);CLR(b);CLR(c);for(int i=0; i<n; ++i)a[i].r=A[i]-'0';for(int i=0; i<m; ++i)b[i].r=B[i]-'0';fft(a, len, 1);fft(b, len, 1);for(int i=0; i<len; ++i)c[i]=a[i]*b[i];fft(c, len, -1);for(int i=0; i<len; ++i)C[i]+=c[i].r+0.5; } void getfft() {lena=lenb=0;for(int i=7; i<lenn; i+=8)sa[lena++]=s1[i];for(int i=lenm-1; i>=0; i-=8)sb[lenb++]=s2[i];dofft(sa, sb, got, lena, lenb);for(int i=0; i<lena; ++i)sa[i]=sa[i]=='0'?'1':'0';for(int i=0; i<lenb; ++i)sb[i]=sb[i]=='0'?'1':'0';dofft(sa, sb, got, lena, lenb); } int main() {int n, m;scanf("%d%d", &n, &m);lenn=n*8, lenm=m*8;char *it;it=s1;for(int i=0; i<n; ++i) {scanf("%s", it);for(; *it; ++it) {if(*(it+1)) {sa[lena++]=*it;}}}it=s2;for(int i=0; i<m; ++i) {scanf("%s", it);for(; *it; ++it) {if(*(it+1)) {sb[lenb++]=*it;}}}getkmp();getfft();if(!pos.size()) {puts("No");return 0;}int ans1=n, ans2=~0u>>1;for(int i=0, len=pos.size(); i<len; ++i) {int p=pos[i], t=(m-got[p+m-1]);if(ans2==t) {ans1=min(p, ans1);}else if(ans2>t) {ans2=t;ans1=p;}}printf("Yes\n%d %d\n", ans2, ans1+1);return 0; }

總結

以上是生活随笔為你收集整理的弱省互测#2 t3的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。