第二题——match(bzoj4936)
<哈希+栈+分治>
用栈和哈希预处理出$str[l]$所能匹配的最远位置$x=lst[a[l]][s[l-1]]$。
分治,$l$和$x$组成一对左右括号。递归被划分的区间$[x+1,r]$和$[l+1,x-1]$。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+5,TT=1e9+7; 4 int n,top,hash,a[N],p[N],st[N],s[N],nxt[N]; 5 map<int,int>lst[30]; 6 char str[N],ans[N]; 7 8 void solve(int l,int r) { 9 if(l>=r) return ; 10 int x=lst[a[l]][s[l-1]]; 11 while(ans[x]) x=nxt[x]; 12 lst[a[l]][s[l-1]]=nxt[x]; 13 ans[l]=‘(‘,ans[x]=‘)‘; 14 solve(x+1,r); solve(l+1,x-1); 15 } 16 17 int main() { 18 // freopen("match.in","r",stdin); 19 // freopen("match.out","w",stdout); 20 scanf("%s",str); n=strlen(str); 21 p[0]=1; 22 for(int i=1;i<=n;i++) 23 a[i]=str[i-1]-‘a‘+1,p[i]=1ll*p[i-1]*97%TT; 24 for(int i=1;i<=n;i++) { 25 if(st[top]==a[i]) 26 hash=(hash-1ll*st[top]*p[--top]%TT)%TT; 27 else { 28 st[++top]=a[i]; 29 hash=(hash+1ll*a[i]*p[top-1]%TT)%TT; 30 } 31 s[i]=(hash+TT)%TT; 32 } 33 if(top) return puts("-1"),0; 34 for(int i=1;i<=n;i++) 35 nxt[i]=lst[a[i]][s[i]],lst[a[i]][s[i]]=i; 36 solve(1,n); 37 for(int i=1;i<=n;i++) putchar(ans[i]); 38 return 0; 39 }
原文:https://www.cnblogs.com/qq8260573/p/11180922.html