1. 程式人生 > 實用技巧 >Count New String

Count New String

C. Count New String

參考:Count New String(廣義SAM)

把所有的字串都存進去,然後再求出不同的子串個數即可。

// Created by CAD
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e6+5;
struct state{
    int len,link;
    vector<int> Next;
    state(){Next.resize(10);}
}st[maxn];
int siz=0,last=0;
void init(){
    st[0].len=0;
    st[0].link=-1;
}
void extend(int c){
    int cur=++siz;
    st[cur].len=st[last].len+1;
    int p=last;
    while(~p&&!st[p].Next[c]){
        st[p].Next[c]=cur;
        p=st[p].link;
    }
    if(p==-1) st[cur].link=0;
    else{
        int q=st[p].Next[c];
        if(st[p].len+1==st[q].len) st[cur].link=q;
        else{
            int clone=++siz;
            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=st[cur].link=clone;
        }
    }
    last=cur;
}

int pos[maxn];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string s;cin>>s;s=" "+s;
    init();
    int n=s.length()-1;
    pos[n+1]=0;
    stack<int> stk;
    for(int i=n;i>=1;--i){
        while(!stk.empty()&&s[stk.top()]<s[i]) stk.pop();
        int k=stk.empty()?n+1:stk.top();
        last=pos[k];
        for(int j=i;j<k;++j) extend(s[i]-'a');
        pos[i]=last;
        stk.push(i);
    }
    ll ans=0;
    for(int i=1;i<=siz;++i) ans+=st[i].len-st[st[i].link].len;
    cout<<ans<<endl;
    return 0;
}