BZOJ 3555: [Ctsc2014]企鹅QQ
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 3555: [Ctsc2014]企鹅QQ
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
似乎大家全部都用的是hash?那我講一個不用hash的做法吧。
首先考慮只有一位不同的是哪一位,那么這一位前面的位上的字符一定是全部相同,后面的字符也是全部相同。首先考慮后面的字符。
我們對n個串的反串建trie樹,這樣,每一個后綴就對應一個trie樹上的唯一一個節點,不同的后綴對應的就是不同的節點,這樣就不用hash表了。
但是字符集很大,用trie空間太大,那么就用鄰接表或map存邊就好了。
然后就是令前綴全部相同。那么我們從左到右枚舉每一位,按照當前位的字符進行分治,當前位不同的就通過后綴計算貢獻,相同的就放在一起,繼續分治即可。
然后就跑的飛快,目前是BZOJ rk2,Luogu rk1。
實現的時候有很多細節,具體請參考代碼。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cctype> #define qmin(x,y) (x=min(x,y)) #define qmax(x,y) (x=max(x,y)) #define vi vector<int> #define vit vector<int>::iterator #define pir pair<int,int> #define fr first #define sc second #define mp(x,y) make_pair(x,y) #define rsort(x,y) sort(x,y),reverse(x,y) using namespace std;inline char gc() { // static char buf[100000],*p1,*p2; // return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;return getchar(); }template<class T> int read(T &ans) {ans=0;char ch=gc();T f=1;while(!isdigit(ch)) {if(ch==EOF) return -1;if(ch=='-') f=-1;ch=gc();}while(isdigit(ch))ans=ans*10+ch-'0',ch=gc();ans*=f;return 1; }template<class T1,class T2> int read(T1 &a,T2 &b) {return read(a)!=EOF&&read(b)!=EOF?2:EOF; }template<class T1,class T2,class T3> int read(T1 &a,T2 &b,T3 &c) {return read(a,b)!=EOF&&read(c)!=EOF?3:EOF; }typedef long long ll; const int Maxn=6100000; const int Maxm=31000; const int Maxl=210; const int inf=0x3f3f3f3f;int to[Maxn],nxt[Maxn],first[Maxn],tot=1; char w[Maxn],s[Maxm][Maxl]; int p[Maxm][Maxl],n,len,x,po[Maxl][Maxl],qq[Maxl],bj[Maxl],ans; int a[Maxm],siz[Maxl],b[Maxm],tn[Maxn],cnt=1; queue<int> q[Maxl];inline void add(int u,int v,char wi) {to[tot]=v;nxt[tot]=first[u];w[tot]=wi;first[u]=tot++; }void solve(int l,int r,int cur) {if(l>r) return ;if(cur==len) return ;int cnt=0;for(int i=l;i<=r;i++) {int x=s[a[i]][cur];q[x].push(a[i]);siz[x]++;if(!bj[x]) qq[++cnt]=x,bj[x]=1;}if(cnt==1) {for(int i=1;i<=cnt;i++) bj[qq[i]]=siz[qq[i]]=0;while(!q[qq[1]].empty()) q[qq[1]].pop();solve(l,r,cur+1);}else {int sxz,zhy=0;for(int i=1;i<=cnt;i++) {if(siz[qq[i]]>zhy) {sxz=i;zhy=siz[qq[i]];}}swap(qq[cnt],qq[sxz]);int las=l;po[cur][0]=las;for(int i=1;i<cnt;i++) {int x=qq[i],num=0;while(!q[x].empty()) {int now=q[x].front();q[x].pop();b[++num]=p[now][cur+1];ans+=tn[b[num]];a[las++]=now;}while(num) tn[b[num--]]++;po[cur][i]=las;}while(!q[qq[cnt]].empty()) {int now=q[qq[cnt]].front();q[qq[cnt]].pop();ans+=tn[p[now][cur+1]];a[las++]=now;} po[cur][cnt]=las;for(int i=l;i<po[cur][cnt-1];i++) tn[p[a[i]][cur+1]]--;for(int i=1;i<=cnt;i++) bj[qq[i]]=siz[qq[i]]=0;for(int i=1;i<=cnt;i++)solve(po[cur][i-1],po[cur][i]-1,cur+1);} }signed main() { // freopen("test.in","r",stdin);read(n,len,x);for(int i=1;i<=n;i++) {scanf("%s",s[i]);int now=1;for(int j=len-1;j>=0;j--) {int temp=0;for(int k=first[now];k;k=nxt[k])if(w[k]==s[i][j]) {temp=to[k];break;}if(!temp) add(now,++cnt,s[i][j]),temp=cnt;now=temp;p[i][j]=now;}}for(int i=1;i<=n;i++) a[i]=i;solve(1,n,0);printf("%d\n",ans);return 0; }轉載于:https://www.cnblogs.com/shanxieng/p/10783697.html
總結
以上是生活随笔為你收集整理的BZOJ 3555: [Ctsc2014]企鹅QQ的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模型解释器-LIME
- 下一篇: 梁宁《产品思维》之26三级火箭