two strings
Posted dyzll
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,有五种操作,操作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; }
以上是关于two strings的主要内容,如果未能解决你的问题,请参考以下文章