zoukankan      html  css  js  c++  java
  • two strings

    A1484. two strings(罗干)

    时间限制1.0s   内存限制256.0MB
    【问题描述】
      给定两个字符串A和B,有五种操作,操作1为在A串开头添加一个字符,操作2为在A串结尾添加一个字符,操作3为在B串开头添加一个字符,操作4为在B串结尾添加一个字符,操作5为询问当前的B串在当前A串中出现的次数。保证字符均为小写字母,且A、B串初始非空。
    【输入格式】
      第一行第二行分别为初始的A串和B串;
      第三行一个整数m,表示操作的次数;
      接下来m行,每行表示一个操作,每行第一个数为一个在1-5之间的数字,若其值不为5,则在数字后会有一个小写字母。
    【输出格式】
      对于每个询问,每行输出一个整数,表示B串在A串中出现的次数。
    【样例输入】
      ababc
      a
      7
      5
      4 b
      5
      3 a
      1 a
      5
      5
    【样例输出】
      2
      2
      1
      1
    【数据规模】
      10%的数据中,最终A串和B串长度之和小于等于200,操作数小于等于10。
      30%的数据中,最终A串和B串长度之和小于等于2000,操作数小于等于1000。
      100%的数据中,最终A串和B串长度之和小于等于200000,操作数小于等于200000。
    分析:对最终的A串和B串用分隔符拼接,构建后缀数组,模拟这m次操作;
       可以发现对于在A串或B串添加字符,最多会影响一个位置的可行性;
       在后缀数组中查找字符串可以使用二分找到连续区间,询问区间的合法性可以使用树状数组实现;
    代码:
      
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10,inf=0x3f3f3f3f;
    int n,m,k,t,d[maxn],tot;
    void add(int x,int y){while(x<=tot)d[x]+=y,x+=x&(-x);}
    int get(int x){int ret=0;while(x)ret+=d[x],x-=x&(-x);return ret;}
    struct query{int op,pos;}q[maxn];
    struct node{int x,id,nt;}e[maxn];
    char ch[maxn];
    int cntA[maxn],cntB[maxn];
    int sa[maxn],lev[maxn],height[maxn];
    int A[maxn],B[maxn],tsa[maxn];
    int mi[20][maxn],p[maxn];
    int ask(int l,int r)
    {
        int x=p[r-l+1];
        return min(mi[x][l],mi[x][r-(1<<x)+1]);
    }
    void solve(int n,int m)
    {
        for (int i = 0; i < m; i ++) cntA[i] = 0;
        for (int i = 1; i <= n; i ++) cntA[ch[i]] ++;
        for (int i = 1; i < m; i ++) cntA[i] += cntA[i - 1];
        for (int i = n; i; i --) sa[cntA[ch[i]] --] = i;
        lev[sa[1]] = 1;
        for (int i = 2; i <= n; i ++)
        {
            lev[sa[i]] = lev[sa[i - 1]];
            if (ch[sa[i]] != ch[sa[i - 1]]) lev[sa[i]] ++;
        }
        for (int l = 1; lev[sa[n]] < n; l <<= 1)
        {
            memset(cntA,0,sizeof(cntA[0])*(n+1));
            memset(cntB,0,sizeof(cntB[0])*(n+1));
            for (int i = 1; i <= n; i ++)
            {
                cntA[A[i] = lev[i]] ++;
                cntB[B[i] = (i + l <= n) ? lev[i + l] : 0] ++;
            }
            for (int i = 1; i <= n; i ++) cntB[i] += cntB[i - 1];
            for (int i = n; i; i --) tsa[cntB[B[i]] --] = i;
            for (int i = 1; i <= n; i ++) cntA[i] += cntA[i - 1];
            for (int i = n; i; i --) sa[cntA[A[tsa[i]]] --] = tsa[i];
            lev[sa[1]] = 1;
            for (int i = 2; i <= n; i ++)
            {
                lev[sa[i]] = lev[sa[i - 1]];
                if (A[sa[i]] != A[sa[i - 1]] || B[sa[i]] != B[sa[i - 1]]) lev[sa[i]] ++;
            }
        }
        for (int i = 1, j = 0; i <= n; i ++)
        {
            if (j) j --;
            while (ch[i + j] == ch[sa[lev[i] - 1] + j]) j ++;
            height[lev[i]] = j;
        }
    }
    int main() {
        int i,j;
        //freopen("in.txt","r",stdin);
        tot=0;
        int ha=-1,ta=-1,hb=-1,tb=-1;
        scanf("%s",ch+1);
        for(i=1;ch[i];i++)
        {
            e[tot].x=ch[i]-'a';
            if(!~ha)ha=ta=tot;
            else e[ta].nt=tot,ta=tot;
            tot++;
        }
        scanf("%s",ch+1);
        for(i=1;ch[i];i++)
        {
            e[tot].x=ch[i]-'a';
            if(!~hb)hb=tb=tot;
            else e[tb].nt=tot,tb=tot;
            tot++;
        }
        //cout<<ha<<" "<<ta<<" "<<hb<<" "<<tb<<endl;
        scanf("%d",&m);
        for(i=1;i<=m;i++)
        {
            int op;
            char str[2];
            scanf("%d",&op);
            q[i].op=op;
            if(op==5)continue;
            scanf("%s",str);
            e[tot].x=str[0]-'a';
            e[tot].id=i;
            if(op==1)
            {
                e[tot].nt=ha;
                ha=tot;
            }
            else if(op==2)
            {
                e[ta].nt=tot;
                ta=tot;
            }
            else if(op==3)
            {
                e[tot].nt=hb;
                hb=tot;
            }
            else if(op==4)
            {
                e[tb].nt=tot;
                tb=tot;
            }
            tot++;
        }
        tot=0;
        int sx,sy,ex,ey;
        sx=sy=-1;
        for(i=ha;;i=e[i].nt)
        {
            ch[++tot]=e[i].x;
            if(e[i].id)q[e[i].id].pos=tot;
            else {if(!~sx)sx=tot;ex=tot;}
            if(i==ta)break;
        }
        ch[++tot]=26;
        for(i=hb;;i=e[i].nt)
        {
            ch[++tot]=e[i].x;
            if(e[i].id)q[e[i].id].pos=tot;
            else {if(!~sy)sy=tot;ey=tot;}
            if(i==tb)break;
        }
        solve(tot,27);
        for(i=2;i<=tot;i++)p[i]=1+p[i>>1];
        for(i=0;1<<i<=tot;i++)
        {
            for(j=1;j+(1<<i)<=tot;j++)
            {
                if(!i)mi[i][j]=height[j];
                else mi[i][j]=min(mi[i-1][j],mi[i-1][j+(1<<(i-1))]);
            }
        }
        //cout<<sx<<" "<<ex<<" "<<sy<<" "<<ey<<endl;
        for(i=sx;i+ey-sy<=ex;i++)add(lev[i],1);
        for(i=1;i<=m;i++)
        {
            int op=q[i].op;
            if(op==1)
            {
                sx--;
                if(sx+ey-sy<=ex)add(lev[sx],1);
            }
            else if(op==2)
            {
                ex++;
                if(sx+ey-sy<=ex)add(lev[ex-ey+sy],1);
            }
            else if(op==3)
            {
                sy--;
                if(ex-ey+sy+1>=sx)add(lev[ex-ey+sy+1],-1);
            }
            else if(op==4)
            {
                ey++;
                if(ex-ey+sy+1>=sx)add(lev[ex-ey+sy+1],-1);
            }
            else
            {
                int pos=lev[sy],len=ey-sy+1;
                int l=1,r=pos-1,pl=pos,pr=pos;
                while(l<=r)
                {
                    int mid=l+r>>1;
                    if(ask(mid+1,pos)>=len)pl=mid,r=mid-1;
                    else l=mid+1;
                }
                l=pos+1,r=tot;
                while(l<=r)
                {
                    int mid=l+r>>1;
                    if(ask(pos+1,mid)>=len)pr=mid,l=mid+1;
                    else r=mid-1;
                }
                printf("%d
    ",get(pr)-get(pl-1));
            }
        }
        return 0;
    }
  • 相关阅读:
    再谈H2的MVStore与MVMap
    log4j动态日志级别调整
    wireshark抓文件上传的包的结果记录
    struts2对properties资源的处理
    Spring core resourc层结构体系及JDK与Spring对classpath中资源的获取方式及结果对比
    [工具使用] visualvm 通过jmx不能连接
    oracle 安装 启动listener 建库相关
    vscode
    XSSFWorkbook
    TearmQuery()
  • 原文地址:https://www.cnblogs.com/dyzll/p/9594974.html
Copyright © 2011-2022 走看看