zoukankan      html  css  js  c++  java
  • BZOJ5137[Usaco2017 Dec]Standing Out from the Herd

    看了半天题 不知道怎么用SAM维护 于是借(chao)鉴(xi)的一发神犇的 只要判断这个子串之前被标记的记号(也就是他属于第几个串)和这次转移到的是否相同 如果不同就说明该子串属于多个串 直接标记-1 依次转移就好咧 最后统计就是ans[f[i]]+=sam[i].mxsam[par[i]].mx;f[i]就是他属于那个串

    #include<bits/stdc++.h>
    #define bug(x) cout<<(#x)<<" "<<(x)<<endl
    #define ll long long
    using namespace std;
    const int N=2e5+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;
    }
    struct Edge{
        int v,nxt;
    }e[N*2];
    struct data{
        int a[26],c;
    }tr[N];
    struct SAM{
        int par,mx,a[26];
    }sam[N];
    int tot,rt,rttot,cnt=1,n,len,r[N],head[N];
    ll ans[N];
    char s[N]; 
    void ins(int u,int v){
        e[++tot].v=v,e[tot].nxt=head[u],head[u]=tot;
    }
    void update(int&c,int op){
        if(c==0) c=op;
        else c=(c==op)?c:-1;
    }
    int add(int p,int c,int op){
        int np=++rttot;
        sam[np].mx=sam[p].mx+1;
        update(r[np],op);
        for(;p&&!sam[p].a[c];p=sam[p].par) sam[p].a[c]=np;
        if(!p) sam[np].par=rt;
        else{
            int q=sam[p].a[c];
            if(sam[q].mx==sam[p].mx+1) sam[np].par=q;
            else{
                int nq=++rttot;
                sam[nq]=sam[q];
                sam[nq].mx=sam[p].mx+1;
                sam[q].par=sam[np].par=nq;
                for(;p&&sam[p].a[c]==q;p=sam[p].par) sam[p].a[c]=nq;
            }
        }
        return np;
    }
    void build(int op){
        int len=strlen(s+1),x=1;
        for(int i=1;i<=len;i++){
            update(tr[x].c,op);
            int c=s[i]-'a';
            if(!tr[x].a[c]) tr[x].a[c]=++cnt;
            x=tr[x].a[c];
        }
        update(tr[x].c,op);
    }
    void built(int x,int c,int p){
        int np;
        if(x==1) np=1;
        else np=add(p,c,tr[x].c);
        //bug(np);
        for(int i=0;i<26;i++) if(tr[x].a[i]) built(tr[x].a[i],i,np);
    }
    void dfs(int x){
        for(int i=head[x];i;i=e[i].nxt){
            int j=e[i].v;
            dfs(j);
            update(r[x],r[j]);
        }
        if(x!=1&&r[x]!=-1) ans[r[x]]+=sam[x].mx-sam[sam[x].par].mx; 
    }
    int main(){
    #ifdef Devil_Gary
        freopen("in.txt","r",stdin);
    #endif
        rttot=rt=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%s",s+1),
            build(i); 
        }
        built(1,0,0);
        for(int i=2;i<=rttot;i++) ins(sam[i].par,i);
        dfs(1);
        for(int i=1;i<=n;i++) printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    开博语
    ch8 固定宽度、流式、弹性布局
    ch8 让div居中--使用外边距
    ch8 基于浮动的布局(两列浮动布局、三列浮动布局)
    ch3 盒模型、定位
    事件类型--鼠标与滚轮事件
    事件类型-UI事件、焦点事件
    事件对象
    事件处理程序
    内存和性能--事件委托、移除事件处理程序
  • 原文地址:https://www.cnblogs.com/devil-gary/p/8893464.html
Copyright © 2011-2022 走看看