BZOJ4566 [Haoi2016]找相同字符 SAM+拓扑

来源:互联网 发布:金十数据官网外汇 编辑:程序博客网 时间:2024/05/18 00:45

学了几天SAM学了 这道题总算是领会到了些许 对parent树有了更深的理解 但是我还是不能表述出来 太菜了

大家可以去百度CLJ神犇的PPT 讲的很好 附一个百度文库的网址

我们可以先跑出两个串的SAM 对于每一个节点 记录到达此节点的串的数目 这时候要用到拓扑 因为对于一个节点i 如果有两个串能在i匹配 则他一定能下parent[i] 匹配 所以到拓扑将每一个节点的匹配数传给parent 然后因为每一个节点是有len的 所以每个节点的个数应该为(len[i]len[parent[i]])sz[i][0]sz[i][1]求和就好啦

#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;}
阅读全文
'); })();
1 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 工笔画法 工笔画家 工笔仕女 工笔龙画法 工笔佛像 国画工笔花鸟 国画花鸟工笔 国画工笔教程 工笔人物白描 国画工笔人物画 工笔人物画技法 哪里可以学工笔画 怎样画工笔画 工笔画用什么纸 工笔画美人蕉图片 鸟工笔画 工笔画背景素材 工笔画鸟的画法步骤 工笔画培训 现代工笔花鸟画 工笔画是国画吗 工笔画论坛 中国工笔画 牡丹工笔画图片 工笔画教程 工笔画牡丹图片 工笔画照片 工笔画入门教程 工笔画培训班 工笔画批发 工笔画网站 鲤鱼工笔画 荷花工笔画 学工笔画 工笔画的特点 工笔画花 梅花工笔画 山水工笔画 重彩工笔画 工笔画孔雀 工笔画人物教程