美文网首页信息学竞赛题解(IO题解)
BZOJ-2434: [Noi2011]阿狸的打字机(AC自动机

BZOJ-2434: [Noi2011]阿狸的打字机(AC自动机

作者: AmadeusChan | 来源:发表于2018-10-16 20:25 被阅读0次

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2434

明显先建立AC自动机,然后对于y上的每一个点,沿着fail走,能走到x的就答案+1,这个暴力思路很明显,但是明显过不了。

每个节点只有一个fail,那么就把fail作为其父亲节点建fail树,那么,答案就是x的子树中存在的y的节点个数,这个就用DFS序+BIT维护就可以了。

代码:

有没有IO优化再次对比明显了,C++读入个字符串就真的那么慢么。。。(最下面的未加优化)

a044ad345982b2b7759bc4b033adcbef76099bba.jpg.png
#include <cstdio>

#include <algorithm>

#include <cstring>

#include <queue>

 

using namespace std ;

 

#define MAXN 100100

#define lowbit( x )((- x )& x )

#define clear( x )memset( x ,0,sizeof( x ))

#define MAXV 500100

 

int getstr(char*s ){

    int len =0, ch ;

    for( ch =getchar(  );!(( ch >='a'&& ch <='z')|| ch =='B'|| ch =='P'); ch =getchar(  ));

    s[ len ++]= ch ;

    for( ch =getchar(  );( ch >='a'&& ch <='z')|| ch =='B'|| ch =='P'; ch =getchar(  )) s[ len ++]= ch ;

    return len ;

}

 

void getint(int&t ){

    int ch ;

    for( ch =getchar(  );!( ch >='0'&& ch <='9'); ch =getchar(  ));

    t = ch -'0';

    for( ch =getchar(  ); ch >='0'&& ch <='9'; ch =getchar(  )) t *=10, t += ch -'0';

}

   

void putint(int t ){

    if(! t )putchar('0')

    ;else{

        int ans[20];

        ans[0]=0;

        for(; t ; t /=10) ans[++ ans[0]]= t %10;

        for(int i = ans[0]; i ; i --)putchar('0'+ ans[ i ]);

    }

    putchar('\n');

}

 

struct node{

        int fail , father , child[26];

        node (  ){

               fail = father =0;clear( child );

        }

} v[ MAXV ];

 

char s[ MAXN ];

int V =0, cnt =0, w[ MAXN ];

 

void Make_trie(  ){

        int len =getstr( s );

        int t =0;

        for(int i =0; i < len ; i ++){

               if( s[ i ]=='P'){

                       w[++ cnt ]= t ;

               }else if( s[ i ]=='B'){

                       t = v[ t ].father ;

               }else{

                       if(! v[ t ].child[ s[ i ]-'a']) v[ t ].child[ s[ i ]-'a']=++ V ;

                       v[ v[ t ].child[ s[ i ]-'a']].father = t ;

                       t = v[ t ].child[ s[ i ]-'a'];

               }

        }

}

 

queue<int>Q ;

 

void Make_fail(  ){

        while(! Q.empty(  )) Q.pop(  );

        for(int i =0; i <26; i ++)if( v[0].child[ i ]){

               Q.push( v[0].child[ i ]);

        }

        while(! Q.empty(  )){

               int ve = Q.front(  ); Q.pop(  );

               for(int i =0; i <26; i ++)if( v[ ve ].child[ i ]){

                       Q.push( v[ ve ].child[ i ]);int u = v[ ve ].fail ;

                       for(; u &&! v[ u ].child[ i ]; u = v[ u ].fail );

                       v[ v[ ve ].child[ i ]].fail = v[ u ].child[ i ]? v[ u ].child[ i ]:0;

               }

        }

}

 

struct edge{

        edge *next ;

        int t ;

        edge (  ){

               next = NULL ;

        }

}*head[ MAXV ];

 

void AddEdge(int s ,int t ){

        edge *p =new( edge );

        p -> t = t , p -> next = head[ s ];

        head[ s ]= p ;

}

 

int arr[ MAXV *2], in[ MAXV ], out[ MAXV ], Index =0;

 

void dfs(int t ){

        arr[ in[ t ]=++ Index ]= t ;

        for( edge *p = head[ t ]; p ; p = p -> next )dfs( p -> t );

        arr[ out[ t ]=++ Index ]= t ;

}

 

void Fail_tree(  ){

        clear( head );

        for(int i =0; i ++< V ;)AddEdge( v[ i ].fail , i );

        dfs(0);

}

 

struct qtype{

        qtype *next ;

        int x , r ;

}*fro[ MAXV ];

 

void Insert(int s ,int t ,int r ){

        qtype *p =new( qtype );

        p -> x = s , p -> r = r , p -> next = fro[ t ];

        fro[ t ]= p ;

}

 

int m ;

 

void Init_query(  ){

        getint( m );clear( fro );

        for(int i =0; i ++< m ;){

               int s , t ;

               getint( s ),getint( t );Insert( w[ s ], w[ t ], i );

        }

}

 

struct Bit{

        int a[ MAXV *2], N ;

       

        void Init(int _N ){

               N = _N ;clear( a );

        }

       

        void Add(int x ,int y ){

               for(int i = x ; i <= N ; i +=lowbit( i )) a[ i ]+= y ;

        }

       

        int Sum(int l ,int r ){

               int rec =0;

               for(int i = r ; i ; i -=lowbit( i )) rec += a[ i ];

               for(int i = l -1; i ; i -=lowbit( i )) rec -= a[ i ];

               return rec ;

        }

} bit ;

 

int ans[ MAXN ];

 

void Dfs(int t ){

        bit.Add( in[ t ],1);

        for( qtype *p = fro[ t ]; p ; p = p -> next )

            ans[ p -> r ]= bit.Sum( in[ p -> x ], out[ p -> x ]);

        for(int i =0; i <26; i ++)if( v[ t ].child[ i ]){

               Dfs( v[ t ].child[ i ]);

        }

        bit.Add( out[ t ],-1);

}

 

void Solve(  ){

        bit.Init( Index );

        Dfs(0);

}

 

int main(  ){

        Make_trie(  );

        Make_fail(  );

        Fail_tree(  );

        Init_query(  );

        Solve(  );

        for(int i =0; i ++< m ;)putint( ans[ i ]);

        return 0;

}

相关文章

网友评论

    本文标题:BZOJ-2434: [Noi2011]阿狸的打字机(AC自动机

    本文链接:https://www.haomeiwen.com/subject/oukkzftx.html