two strings
阿新 • • 發佈:2018-09-06
names 樹狀 freopen -s 後綴 接下來 node div color
給定兩個字符串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串添加字符,最多會影響一個位置的可行性;
在後綴數組中查找字符串可以使用二分找到連續區間,詢問區間的合法性可以使用樹狀數組實現;
代碼:
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);returnret;} 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\n",get(pr)-get(pl-1)); } } return 0; }
two strings