IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [航海协会]基因切割 -> 正文阅读

[数据结构与算法][航海协会]基因切割

基因切割

题目概述

在这里插入图片描述
在这里插入图片描述

题解

由于 N O I = I O N = I n s t i t u t e ? o f ? N a v i g a t i o n = 航 海 协 会 NOI=ION=Institute\,of\,Navigation=航海协会 NOI=ION=InstituteofNavigation=,所以就叫这段时间的模拟赛题航海协会吧。

我们可以将题目稍微转化一下,很容易发现他那种复杂的匹配方法可以等价于依次对于 i = 1 , . . . , m i=1,...,m i=1,...,m暴力找到整个串中的 T i T_i Ti?,将它们删掉。
那么显然就可以 O ( ∑ ∣ T ∣ 2 m ) O\left(\sum |T|^2m\right) O(T2m)直接暴力匹配,再加一个KMP优化一下,就只要 O ( ∑ ∣ T ∣ n ) O\left(\sum |T|n\right) O(Tn)了。

我们想想我们的复杂度是被卡在每一次都要跑整个串上,我们能否先将一部分答案用其他的方式处理出来。
我们不妨先预设一个阈值 B B B,对于小于 B B B的字符串,我们可以先建立一棵 T r i e Trie Trie树,然后对于每个前缀的长度不超过 B B B的后缀,放到 T r i e Trie Trie树上跑,看能够匹配到的最靠前的询问串是哪一个,放到该询问串的集合中,等到处理这个询问串的时候,就将集合中的串拿出来一个一个删掉。
可以发现,每次我们从原串中删掉一部分,都势必导致一些包含删掉元素的串发生改变。
显然,我们删掉的串是一个连续串,所以只会影响到后面的 B B B位,将它们重新找一下即可。
显然,我们每次重新找,都会消耗 O ( B 3 ) O(B^3) O(B3)的时间,如果倒过来建Trie树,就可以优化到 B 2 B^2 B2,因为这样就只用找Trie树一条路径上的最小值。
注意,当我们取出一个集合中的元素删掉时也有可能影响这个集合中其它元素的值,所以应该每次取出一个集合中最靠前的串删掉。

至于我们如何维护原串现在还没被删掉的位置,我们可以考虑使用链表的结构,将每个被删掉的区间连在一起,因为我们在串上跳每一步也最多只会经过一个被完全删掉的区间,直接将它跳过即可。
而询问串是可能相同的,所以我们可以用内设前向星的方式维护Trie树上每个节点的对应值,当这个询问串被操作后,就跳到下一个询问串上。
注意一下,同一个询问串导致删掉的区间是不能包含的。

时间复杂度 O ( n 2 B + n B 2 ? n 2 3 ) O\left(\frac{n^2}{B}+nB^2\geqslant n^{\frac{2}{3}}\right) O(Bn2?+nB2?n32?),当 B B B n 1 3 n^{\frac{1}{3}} n31?时最优。
跑得超级快,至少比 b i t s e t bitset bitset做法快 3 3 3倍。

源码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define MAXN 110005
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lowbit(x) (x&-x)
#define lson (rt<<1)
#define rson (rt<<1|1)
const int n1=50;
const int INF=0x3f3f3f3f;
template<typename _T>
void read(_T &x){
    _T f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
    x*=f;
}
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1;}return t;}
char str[MAXN],ttr[MAXN];bool vis[MAXN];
int m,n,bg[MAXN],ed[MAXN],len[MAXN],a[MAXN],b[MAXN],nxt[MAXN],pos[MAXN];
int stak,sta[MAXN],belong[MAXN],t[MAXN],stb[MAXN],stk,tt[MAXN],tp,L[MAXN],R[MAXN];
set<int>st[MAXN];
int turn(char x){
    if(x=='A')return 0;
    if(x=='C')return 1;
    if(x=='G')return 2;
    return 3;
}
struct ming{
    int ch[5],val;
    ming(){for(int i=0;i<4;i++)ch[i]=0;val=0;}
};
class TrieTree{
    private:
        int tot,root;ming tr[MAXN];
    public:
        void init(){root=++tot;}
        void insert(int id){
            int now=root;
            for(int i=1;i<=stak;i++){
                if(!tr[now].ch[sta[i]])
                    tr[now].ch[sta[i]]=++tot;
                now=tr[now].ch[sta[i]];
            }
            pos[id]=now;nxt[id]=tr[now].val;tr[now].val=id;//,printf("%d modify in %d\n",id,now);
        }
        int query(int dn){
            int now=root,res=INF;
            for(int i=1;i<=stak;i++){
                now=tr[now].ch[sta[i]];if(!now)break;
                //printf("we get in %d\n",now);
                if(tr[now].val>=dn)res=min(res,tr[now].val);
                else if(nxt[tr[now].val]>=dn)res=min(res,nxt[tr[now].val]);
            }
            if(res>INF-1)return 0;return res;
        }
        void modify(int x){tr[x].val=nxt[tr[x].val];}
}T;
void insert(int x){
    vis[x]=1;L[x]=R[x]=x;
    if(vis[x+1])L[R[x+1]]=L[x],R[L[x]]=R[x+1];
    if(vis[x-1])L[R[x]]=L[x-1],R[L[x-1]]=R[x];
}
int askpre(int x){return !vis[x-1]?x-1:L[x-1]-1;}
int asksuf(int x){return !vis[x+1]?x+1:R[x+1]+1;}
int main(){
    freopen("dna.in","r",stdin);
    freopen("dna.out","w",stdout);
    scanf("%s",str+1);n=(int)strlen(str+1);read(m);T.init();
    for(int i=1;i<=n;i++)a[i]=turn(str[i]);
    for(int i=1;i<=m;i++){
        bg[i]=ed[i-1]+1;scanf("%s",ttr+bg[i]);
        len[i]=(int)strlen(ttr+bg[i]);ed[i]=bg[i]+len[i]-1;
        for(int j=bg[i];j<=ed[i];j++)b[j]=turn(ttr[j]);
    }
    for(int i=m;i>0;i--)if(len[i]<=n1){
        for(int j=ed[i];j>=bg[i];j--)sta[++stak]=b[j];
        T.insert(i);stak=0;
    }
    for(int i=1;i<=n;i++){
        stak=0;for(int j=i;j>max(0,i-n1);j--)sta[++stak]=a[j];
        belong[i]=T.query(1);if(belong[i])st[belong[i]].insert(i);
    }
    int tot=0;
    for(int i=1;i<=m;i++){
        if(len[i]<=n1){
            while(!st[i].empty()){
                int x=*st[i].begin(),l=x,r=asksuf(x);stk=0;
                for(int j=1;j<=len[i];j++){
                    int t=l;l=askpre(l);insert(t);
                    if(belong[t])st[belong[t]].erase(t);
                }
                for(int j=1;j<n1&&l;j++)stb[++stk]=l,l=askpre(l);
                reverse(stb+1,stb+stk+1);
                for(int j=1;j<n1&&r<=n;j++)stb[++stk]=r,r=asksuf(r);
                int num=0;tot++;
                for(int j=1;j<=stk;j++){
                    if(stb[j]<=x)continue;int x=stb[j];stak=0;
                    for(int k=j;k>max(j-n1,0);k--)
                        sta[++stak]=a[stb[k]];
                    if(belong[x])st[belong[x]].erase(x);
                    num++;belong[x]=T.query(i+(num<len[i]));
                    if(belong[x])st[belong[x]].insert(x);
                }
            }
            T.modify(pos[i]);
        }
        else{
            for(int j=2;j<=len[i];j++){
                int now=t[j-1];while(now&&b[now+bg[i]]!=b[j+bg[i]-1])now=t[now];
                t[j]=(b[now+bg[i]]==b[j+bg[i]-1])?now+1:0;
            }
            tp=0;
             for(int j=1,las=0;j<=n;j++)if(!vis[j]){
                while(las&&b[las+bg[i]]!=a[j])las=t[las];
                las=(b[las+bg[i]]==a[j])?las+1:0;tt[++tp]=j;
                if(las==len[i]){
                    int x=j,l=x,r=asksuf(x);stk=las=0;
                    for(int k=1;k<=len[i];k++){
                        int t=l;l=askpre(l);insert(t);
                        if(belong[t])st[belong[t]].erase(t);
                    }
                    for(int k=1;k<n1&&l;k++)stb[++stk]=l,l=askpre(l);
                    reverse(stb+1,stb+stk+1);
                    for(int k=1;k<n1&&r<=n;k++)stb[++stk]=r,r=asksuf(r);
                    for(int k=1;k<=stk;k++){
                        if(stb[k]<=x)continue;int x=stb[k];stak=0;
                        for(int l=k;l>max(k-n1,0);l--)
                            sta[++stak]=a[stb[l]];
                        if(belong[x])st[belong[x]].erase(x);
                        belong[x]=T.query(i);
                        if(belong[x])st[belong[x]].insert(x);
                    }
                }
            }
        }
    }
    for(int i=1;i<=n;i++)if(!vis[i])printf("%c",str[i]);puts("");
    return 0;
}

谢谢!!!

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:59:06  更:2022-05-09 13:02:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:24:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码