2019HNCPC C Distinct Substrings suffix automaton

The meaning of problems

Given a string of length n, the size of the character set of m (1 <= n, m <= 1e6), seeking \ (\ bigoplus_ {c = 1 } ^ {m} \ left (h (c) \ cdot 3 ^ c \ bmod (10 ^ 9 + 7) \ right) \) values. Where H (c) the nature of the newly created string is added to the end of the c number of different substrings.

Problem-solving ideas

When the game did not do it, when listening to find award SAM can be used to do after lts and lsx spoke, and the board a little change to change it.

DETAILED new character is added each time a maximum of two nodes, depending on the nature of the SAM, after a new node is added to the c essentially different number of substrings contribution is H (c), with len [i] -len [link [i ]] will be able to work out.

Live tournament when I did not expect after adding nodes to how to delete this node again, did not want to come out at once, and then just do it D digital DP, but is actually very simple, it is possible to extend the function altered, for asked only count answer is not to modify the original node, so that you do not need to delete; or modify the number of nodes with which a container records, interviews finished and then change it back again to traverse. These two methods should all \ (O (1) \) to modify.

Code

And sister of the standard process to fork take no mistake, it should be right now

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1e6+5;
const int mod=1e9+7;

struct Suffix_Automaton{
    struct state{
        int len,link;
        map<int,int>next;
    }st[maxn<<1];
    int last,tot;
    
    int sz;
    
    void init(){
        st[1].len=0;st[0].link=0;
        st[1].next.clear();
        last=tot=1;;
    }
    int newnode(){
        ++tot;
        st[tot].len=st[tot].link=0;
        st[tot].next.clear();
        return tot;
    }
    void extend(int c){
        int p=last;
        int cur=newnode();
        st[cur].len=st[last].len+1;
        last=cur;
        while(p && !st[p].next.count(c)){
            st[p].next[c]=cur;
            p=st[p].link;
        }
        if(!p)st[cur].link=1;
        else{
            int q=st[p].next[c];
            if(st[p].len+1==st[q].len)st[cur].link=q;
            else{
                int clone=newnode();
                st[clone].len=st[p].len+1;
                st[clone].next=st[q].next;
                st[clone].link=st[q].link;
                st[q].link=st[cur].link=clone;
                while(st[p].next[c]==q){
                    st[p].next[c]=clone;
                    p=st[p].link;
                }
            }
        }
    }
    ll solve(int c){
        ll res=0;
        
        int p=last;
        int cur=newnode();
        st[cur].len=st[last].len+1;
        //last=cur;
        while(p && !st[p].next.count(c)){
            //st[p].next[c]=cur;
            p=st[p].link;
        }
        if(!p){
            st[cur].link=1;
            res=st[cur].len-st[st[cur].link].len;
        }
        else{
            int q=st[p].next[c];
            if(st[p].len+1==st[q].len){
                st[cur].link=q;
                res=st[cur].len-st[st[cur].link].len;
            }
            else{
                int clone=newnode();
                st[clone].len=st[p].len+1;
                //st[clone].next=st[q].next;
                st[clone].link=st[q].link;
                //while(p && st[p].next[c]==q){
                    //st[p].next[c]=clone;
                    //p=st[p].link;
                //}
                //st[q].link=clone;
                st[cur].link=clone;
                
                //结点q的link变为clone,所以需要把原来的删掉再把新的加进去 
                res=((res-(st[q].len-st[st[q].link].len))%mod+mod)%mod;
                res=(res+st[q].len-st[clone].len)%mod;

                res=(res+st[cur].len-st[st[cur].link].len)%mod;
                res=(res+st[clone].len-st[st[clone].link].len)%mod;
            }
        }
        
        tot=sz;
        return (res%mod+mod)%mod;
    }
}S;
int n,m;
int main()
{
    while(~scanf("%d %d",&n,&m)){
        S.init();
        int x;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            S.extend(x);
        }
        S.sz=S.tot;
        ll ans=0,three=1,hc;
        for(int i=1;i<=m;i++){
            three=three*3%mod;
            hc=S.solve(i);
            ans^=(1*hc*three%mod);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zengzk/p/11444479.html