日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://ac.nowcoder.com/acm/contest/72/F


題目大意

nnn個字符串,包括小寫字母和#\##。其中#\##可以替換為任意字符串。求有多少對字符串可能相同。

保證每個字符串至少有一個#\##

2≤n≤500000,∑i=1n∣si∣≤1062\leq n\leq 500000,\sum_{i=1}^n |s_i|\leq 10^62n500000,i=1n?si?106


解題思路

因為可以替換為任意字符串,所以只需要考慮第一個#\##前和最后一個#\##后的部分。

在仔細考慮一下,這個字符串分成前后的兩個部分s,ts,ts,t。數對(x,y)(x,y)(x,y)滿足條件當且僅當sxs_xsx?sys_ysy?的前綴,或者sys_ysy?sxs_xsx?的前綴,且txt_xtx?tyt_yty?的后綴,或者tyt_yty?txt_xtx?的后綴。

放到兩棵TrieTrieTrie樹上就是都有祖先關系就好了,直接跑第一棵上,然后用兩個樹狀數組在第二棵樹上維護就好了。

時間復雜度O(mlog?m)O(m\log m)O(mlogm)


code

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define lowbit(x) (x&-x) using namespace std; const int N=1e6+10; int n,cnt,pos[N],dfn[N],ed[N]; long long ans;char s[N]; vector<int> G[N]; struct TreeBinary{int t[N];void Change(int x,int val){while(x<=cnt){t[x]+=val;x+=lowbit(x);}return;}int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;} }Bf,Bs; struct Trie{int t[N][26],m=1;int Insert(char *s,int n){int x=1;for(int i=1;i<=n;i++){if(s[i]=='#')break;int c=s[i]-'a';if(!t[x][c])t[x][c]=++m;x=t[x][c];}return x;} }Tp,Ts; void dfs(int x){dfn[x]=++cnt;for(int i=0;i<26;i++)if(Ts.t[x][i])dfs(Ts.t[x][i]);ed[x]=cnt; } void work(int x){for(int i=0;i<G[x].size();i++){int p=G[x][i];ans+=Bf.Ask(dfn[pos[p]]);Bf.Change(dfn[pos[p]],1);Bf.Change(ed[pos[p]]+1,-1);ans+=Bs.Ask(ed[pos[p]])-Bs.Ask(dfn[pos[p]]); Bs.Change(dfn[pos[p]],1);}for(int i=0;i<26;i++)if(Tp.t[x][i])work(Tp.t[x][i]);for(int i=0;i<G[x].size();i++){int p=G[x][i];Bs.Change(dfn[pos[p]],-1);Bf.Change(dfn[pos[p]],-1);Bf.Change(ed[pos[p]]+1,1);} } int main() {scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s+1);int l=strlen(s+1);int x=Tp.Insert(s,l);G[x].push_back(i);reverse(s+1,s+1+l);pos[i]=Ts.Insert(s,l);}dfs(1);work(1);printf("%lld\n",ans);return 0; }

總結

以上是生活随笔為你收集整理的Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。