[科技]Loj#6564-最长公共子序列【bitset】

1|0正题

题目链接:https://loj.ac/p/6564


1|1题目大意

给两个序列a,b求它们的最长公共子序列。

1n,m,ai,bi7×104


1|2解题思路

无意间看到的一个bitset科技。

首先设fi,j表示a串匹配到第ib串匹配到第j个时的最长长度,做过dpdp的应该知道fi,j的性质。

0fi,jfi,j11

基本的思路就是设01矩阵M满足fi,j=k=1jMi,k然后用bitset优化转移

然后考虑一下怎么转移,我们先预处理出p数组其中pi表示数字i出现的位置集合

我们的转移要把M中的1尽量的往前移动并且看能否加上一个新的1

假设现在的字符是c,那么我们将使用pc进行转移。

我们把M中每个1作为结尾分成若干段(最后的0也是一段,顺序是从低位到高位)。

那么对于一段中如果这一段pc1那么我们就取最前面的那个1,这样因为前面假设有j1那么这次就匹配pc最前面的那个作为j+1

但是我们显然不可能一段一段做,我们可以考虑怎么把这个操作转成位运算🤔。

考虑一下我们平时是怎么取一个01串的第一位的,我们有lowbit(x)=((x1) xor x) and x对吧。

发现这里每段分开取实际上难实现的地方只有x1,考虑怎么实现这个问题。

因为1是段的末尾,所以每一段的开头前面都是1,所以如果我们让M左移一位那么就变成开头是1了(需要注意补上第一段的1,所以应该是(M<<1)+1

最后来说是

M=(X(M<<1)+1) xor X and X

这样我们就完成了M的转移,因为需要位运算,所以需要手写bitset

时间复杂度O(nmω)

我是看这篇博客学的,看不懂的可以去看下:https://www.cnblogs.com/-Wallace-/p/bit-lcs.html


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ull unsigned long long using namespace std; const int N=7e4+10; int n,m,L; struct bitset{ ull t[N/64+5]; bitset(){memset(t,0,sizeof(t));return;} void set(int p){ t[p>>6]|=(1ull<<(p&63)); return; } void shift(){ ull last=0; for(int i=0;i<L;i++){ ull cur=t[i]>>63; (t[i]<<=1)|=last; last=cur; } return; } int count(){ int ans=0; for(int i=0;i<L;i++) {ull x=t[i];while(x)x-=(x&-x),ans++;} return ans; } bitset& operator=(const bitset &b) {memcpy(t,b.t,sizeof(t));return *this;} bitset& operator|=(const bitset &b){ for(int i=0;i<L;i++)t[i]|=b.t[i]; return *this; } bitset& operator&=(const bitset &b){ for(int i=0;i<L;i++)t[i]&=b.t[i]; return *this; } bitset& operator^=(const bitset &b){ for(int i=0;i<L;i++)t[i]^=b.t[i]; return *this; } }p[N],f,g; bitset operator-(const bitset &a,const bitset &b){ bitset tmp;ull last=0; for(int i=0;i<L;i++){ ull cur=(a.t[i]<b.t[i]+last); tmp.t[i]=a.t[i]-b.t[i]-last; last=cur; } return tmp; } int main() { scanf("%d%d",&n,&m);L=(n>>6)+1; for(int i=1,c;i<=n;i++) scanf("%d",&c),p[c].set(i); for(int i=1,c;i<=m;i++){ scanf("%d",&c); (g=f)|=p[c]; f.shift();f.set(0); f=g-f;f^=g;f&=g; } printf("%d",f.count()); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14963118.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(279)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示