Codeforces round #129 (Div. 1) E. Little elephant and strings

Source: Internet
Author: User

Codeforces round #129 (Div. 1) E. Little elephant and strings

Question: give n strings and ask how many substrings each character string has (different positions, the same substrings are treated as different) appear among at least K of the N strings.

Solution: I learned a new skill of Sam. When creating Sam for these strings, instead of connecting them together and creating Sam, I first set up a trie tree for them, then, search for this trie tree. For the V node on the trie tree, when Sam is being created, it should be located behind his Father's Day on the trie tree, we use TTOM [u] to map the U nodes on the trie tree to the labels on Sam. The advantage of establishing Sam in this way is that I find any prefix of any string, and the node on the Sam that it matches must be the prefix of the string. Let's remember this first. How can we use it for a while. We require that all substrings of each string appear in at least K strings, so let's first look at all substrings, which substrings are contained in K strings and expressed on Sam are the nodes that have been matched by K strings. We use CNT [u] to indicate that the U node has been matched by several strings. Each time we take out a string, it can contribute 1 to the CNT [] value of some nodes. These nodes are the union of each prefix of the string in the node Sam to the root chain, this can be solved by using LCA. After calculating CNT [], check whether the CNT value of each node is greater than or equal to K. If yes, on the node u, the Val [u]-Val [Fa [u] substring is contained by more than K strings. Add [u] is used to represent this value. Finally, when calculating the answer to each string, it is the sum of each prefix of the string mapped to the node on Sam to the add on the Root chain.

Code:

#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#define ll __int64using namespace std ;const int maxn = 111111 ;const int N = maxn << 1;struct Edge {    int to , next ;} edge[N] ;int head[N] , tot , f[N<<1] ;void new_edge ( int a , int b ) {    edge[tot].to = b ;    edge[tot].next = head[a] ;    head[a] = tot ++ ;}char s[maxn] , s1[maxn] ; int l[maxn] , len ;int TtoM[maxn<<1] ;struct LCA {    int dp[22][N<<1] ;    int to[N] , tim[N] ;    int tot , n ;    int MIN ( int a , int b ) {        return tim[a] < tim[b] ? a : b ;    }    void init () {        tot = 0 ;        n = 0 ;    }    void dfs ( int u , int fa ) {        tim[u] = ++ tot ;        for ( int i = head[u] ; i != -1 ; i = edge[i].next ) {            int v = edge[i].to ;            if ( v == fa ) continue ;            dfs ( v , u ) ;            dp[0][++n] = u ;        }        dp[0][++n] = u ;        to[u] = n ;    }    void rmq () {        for ( int i = 1 ; i <= 20 ; i ++ ) {            for ( int j = 1 ; j + (1<<i) - 1 <= n ; j ++ ) {                dp[i][j] = MIN ( dp[i-1][j] , dp[i-1][j+(1<<i-1)] ) ;            }        }    }    int query ( int a , int b ) {        a = to[a] , b = to[b] ;        if ( a > b ) swap ( a , b ) ;        int k = b - a + 1 ;        return MIN ( dp[f[k]][a] , dp[f[k]][b-(1<<f[k])+1] ) ;    }} lca ;namespace SAM  {    int fa[N] , val[N] , c[26][N] ;    int cnt[N] ; int tot , last ;    int ws[N] , wv[N] ;    ll add[N] ;    vector<int> vec[N] ;    void init () ;    void solve ( int , int ) ;    inline int new_node ( int _val ) {        val[++tot] = _val ;        for ( int i = 0 ; i < 26 ; i ++ ) c[i][tot] = 0 ;        cnt[tot] = fa[tot] = add[tot] = 0 ;        vec[tot].clear () ;        return tot ;    }    int ADD ( int k , int p ) {        int i ;        int np = new_node ( val[p] + 1 ) ;        while ( p && !c[k][p] ) c[k][p] = np , p = fa[p] ;        if ( !p ) fa[np] = 1 ;        else {            int q = c[k][p] ;            if ( val[q] == val[p] + 1 ) fa[np] = q ;            else {                int nq = new_node ( val[p] + 1 ) ;                for ( i = 0 ; i < 26 ; i ++ )                    c[i][nq] = c[i][q] ;                fa[nq] = fa[q] ;                fa[q] = fa[np] = nq ;                while ( p && c[k][p] == q ) c[k][p] = nq , p = fa[p] ;            }        }        return np ;    }    void SORT () {        for ( int i = 0 ; i < maxn ; i ++ ) wv[i] = 0 ;        for ( int i = 1 ; i <= tot ; i ++ ) wv[val[i]] ++ ;        for ( int i = 1 ; i < maxn ; i ++ ) wv[i] += wv[i-1] ;        for ( int i = 1 ; i <= tot ; i ++ ) ws[wv[val[i]]--] = i ;    }}namespace Trie {    int c[26][maxn] , tot ;    int new_node () {        for ( int i = 0 ; i < 26 ; i ++ )            c[i][tot] = 0 ;        return tot ++ ;    }    void init () {        tot = 0 ;        new_node () ;    }    void insert ( int n ) {        for ( int i = 1 ; i <= n ; i ++ ) {            int now = 0 ;            for ( int j = l[i] ; j < l[i+1] ; j ++ ) {                int k = s[j] - 'a' ;                if ( !c[k][now] ) c[k][now] = new_node () ;                now = c[k][now] ;            }        }    }}queue<int> Q ;void SAM::init () {    tot = 0 ;    TtoM[0] = new_node ( 0 ) ;    Q.push ( 0 ) ;#define v Trie::c[k][u]    while ( !Q.empty () ) {        int u = Q.front () ; Q.pop () ;        for ( int k = 0 ; k < 26 ; k ++ )            if ( v ){                TtoM[v]=ADD(k,TtoM[u]) ;                Q.push ( v ) ;            }    }}int cmp ( int a , int b ) {    return lca.tim[a] < lca.tim[b] ;}int sta[maxn] ;void SAM::solve ( int n , int k ) {    SORT () ;    for ( int i = 2 ; i <= tot ; i ++ ) {        new_edge ( fa[i] , i ) ;    }    lca.dfs ( 1 , 0 ) ; lca.rmq () ;    for ( int i = 1 ; i <= n ; i ++ ) {        int u = 0 ;        int top = 0 ;        for ( int j = l[i] ; j < l[i+1] ; j ++ ) {            int k = s[j] - 'a' ;            u = v ;            sta[++top] = TtoM[u];            cnt[TtoM[u]] ++ ;        }        sort ( sta + 1 , sta + top + 1 , cmp ) ;        for ( int j = 2 ; j <= top ; j ++ ) {            int w = lca.query ( sta[j-1] , sta[j] ) ;            cnt[w] -- ;        }    }    for ( int i = tot ; i >= 1 ; i -- ) {        int p = ws[i] ;        cnt[fa[p]] += cnt[p] ;        if ( cnt[p] >= k ) add[p] = val[p] - val[fa[p]] ;    }    for ( int i = 1 ; i <= tot ; i ++ ) {        int u = ws[i] ;        for ( int j = head[u] ; j != -1 ; j = edge[j].next ) {            int to = edge[j].to ;            add[to] += add[u] ;        }    }    for ( int i = 1 ; i <= n ; i ++ ) {        int u = 0 ; ll ans = 0 ;        for ( int j = l[i] ; j < l[i+1] ; j ++ ) {            int k = s[j] - 'a' ;            u = v ;            ans += add[TtoM[u]] ;        }        printf ( "%I64d " , ans ) ;    }    puts ( "" ) ;}#undef vvoid init () {    tot = 0 ;    memset ( head , -1 , sizeof ( head ) ) ;    lca.init () ;    Trie::init () ;}int main () {    f[0] = -1 ;    for ( int i = 1 ; i < maxn << 2 ; i ++ )        f[i] = f[i>>1] + 1 ;    int n , k ;    while ( scanf ( "%d%d" , &n , &k ) != EOF ) {        init () ;        len = 0 ;        for ( int i = 1 ; i <= n ; i ++ ) {            scanf ( "%s" , s1 ) ;            int k = strlen ( s1 ) ;            l[i] = len ;            for ( int j = 0 ; j < k ; j ++ )                s[len++] = s1[j] ;        }        l[n+1] = len ;        Trie::insert (n) ;        SAM::init () ;        SAM::solve ( n , k ) ;    }    return 0 ;}/*3 2abcbcab3 2abcacab2 2abcbc1 1bc2 2abb4 4ababbabaaaabbbababaabababababa2 2ababbaba2 2ababab2 2abba*/


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.