BZOJ4566 [Haoi2016]找相同字符 SAM+拓扑
来源:互联网 发布:金十数据官网外汇 编辑:程序博客网 时间:2024/05/18 00:45
学了几天学了 这道题总算是领会到了些许 对
大家可以去百度CLJ神犇的PPT 讲的很好 附一个百度文库的网址
我们可以先跑出两个串的
#include<bits/stdc++.h>#define bug(x) cout<<(#x)<<" "<<(x)<<endl#define ll long long/*char *TT,*mo,but[(1<<15)+2];#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/using namespace std;const int N=8e5+5;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}char s[N]; ll ans;int deg[N],par[N],siz[2][N],ch[N][26],len[N],n,root,sz,last;void extend(int x){ int p=last,np=++sz; len[np]=len[p]+1; for(;p&&!ch[p][x];p=par[p]) ch[p][x]=np; if(!p) par[np]=root; else{ int q=ch[p][x]; if(len[q]==len[p]+1) par[np]=q; else{ int nq=++sz; len[nq]=len[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); par[nq]=par[q];par[q]=par[np]=nq; for(;p&&ch[p][x]==q;p=par[p])ch[p][x]=nq; } }// cout<<np<<" "<<par[np]<<endl; last=np;}void topsort(){ for(int i=1;i<=sz;i++) deg[par[i]]++; queue<int>q; for(int i=1;i<=sz;i++) if(!deg[i]) q.push(i); while(!q.empty()){ int u=q.front();q.pop(); siz[0][par[u]]+=siz[0][u]; siz[1][par[u]]+=siz[1][u];// bug(siz[0][u]),bug(siz[1][u]); deg[par[u]]--; if(!deg[par[u]]) q.push(par[u]); }}int main(){#ifdef Devil_Gary freopen("in.txt","r",stdin);#endif scanf("%s",s+1); n=strlen(s+1); last=sz=root=1; int p=root; for(int i=1;i<=n;i++){ extend(s[i]-'a'); p=ch[p][s[i]-'a']; siz[0][p]++; } scanf("%s",s+1); n=strlen(s+1); last=root;p=root; for(int i=1;i<=n;i++){ extend(s[i]-'a'); p=ch[p][s[i]-'a']; siz[1][p]++; } topsort(); for(int i=1;i<=sz;i++) if(par[i]){// cout<<siz[1][i]<<" "<<siz[0][i]<<endl; ans+=(ll)(len[i]-len[par[i]])*siz[0][i]*siz[1][i]; } return printf("%lld\n",ans),0;}
阅读全文