zoukankan      html  css  js  c++  java
  • 阿狸的打字机

    阿狸的打字机

    首先建立fail树,考虑离线询问。考虑怎么用ACAM处理一个串在另一个串的出现次数,

    可以给询问按照主串分类,对于每一个主串分别处理所有询问。某一个串在主串中出现,主串中位于这个串最后的那个位置跳fail必然可以跳到这个串。所以可以树上差分搞一下

    大概没啥问题?


    然后写了一发,就70了。

    注意到对于100%的数据,没有总长度的限制啊!

    但是由于有 $ n $ 的限制,trie中的总点数是很小的。

    处理方法类似 CF1207G

    • 在将串加入trie的时候,可以记录一个now表示到现在为止加入的串对应在trie上的节点。如果现在要退格,这个点就向上跳,否则在print的时候就往下插入就好了。这样不难发现插入的时候复杂度是线性的。
    • 在处理询问的时候,可以把询问挂在trie上,然后dfs一遍trie处理所有询问。
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include<assert.h>
    using namespace std;
    #define MAXN 1000006
    #define mod 1000000007
    int n , m;
    int len;
    char ch[MAXN] , zh[MAXN]; int en;
    int son[MAXN][26] , fa[MAXN] , fail[MAXN] , num[MAXN] , idx , to[MAXN];
    int cid = 0;
    
    int head1[MAXN] , tt1[MAXN << 1] , nex1[MAXN << 1] , ecn1;
    void ade1( int u , int v ) { 
    //	cout << u <<  ' ' << v << endl;
    	tt1[++ ecn1] = v , nex1[ecn1] = head1[u] , head1[u] = ecn1;
    }
    
    int now = 0 , tim = 0;
    void ins( char* ch , int id ) {
    //	cout << ch << endl;
    	for( int i = 0 ; i < len ; ++ i ) {
    //		printf("%d
    ",++tim);
    		if( !son[now][ch[i] - 'a'] ) son[now][ch[i] - 'a'] = ++ idx , fa[idx] = now , ade1( now , idx );
    		now = son[now][ch[i] - 'a'];
    	}
    	++ num[now] , to[id] = now;
    }
    
    int head[MAXN] , tt[MAXN << 1] , nex[MAXN << 1] , ecn;
    void ade( int u , int v ) { 
    //	cout << u <<  ' ' << v << endl;
    	tt[++ ecn] = v , nex[ecn] = head[u] , head[u] = ecn;
    }
    
    void build( ) {
    	queue<int> Q;
    	for( int i = 0 ; i < 26 ; ++ i ) if( son[0][i] ) Q.push( son[0][i] );
    	while( !Q.empty() ) {
    		int cur = Q.front( ); Q.pop( );
    		ade( fail[cur] , cur );
    		for( int i = 0 ; i < 26 ; ++ i ) 
    			if( son[cur][i] )
    				fail[son[cur][i]] = son[fail[cur]][i] , Q.push( son[cur][i] );
    			else 
    				son[cur][i] = son[fail[cur]][i];
    	}
    }
    struct que { 
    	int t , s , id;
    } Q[MAXN] ;
    bool cmp( que a , que b ) {
    	return a.s < b.s;
    }
    int dfn[MAXN] , R[MAXN] , clo;
    void dfs( int u , int fa ) {
    	dfn[u] = ++ clo;
    	for( int i = head[u] ; i ; i = nex[i] ) {
    		int v = tt[i];
    		dfs( v , u );
    	}
    	R[u] = clo;
    }
    
    namespace fwk {
    	int T[MAXN];
    	void add( int u , int c ) {
    		assert( u );
    		while( u < MAXN ) T[u] += c , u += ( u & -u );
    	}
    	int sum( int u ) {
    		int ret = 0;
    		while( u > 0 ) ret += T[u] , u -= ( u & -u );
    		return ret;
    	}
    }
    vector<pair<int,int> > ques[MAXN];
    int ans[MAXN];
    void dfs1( int u ) {
    	fwk::add( dfn[u] , 1 );
    	for( int i = 0 ; i < ques[u].size() ; ++ i ) 
    		ans[ques[u][i].second] = fwk::sum( R[ques[u][i].first] ) - fwk::sum( dfn[ques[u][i].first] - 1 );
    	for( int i = head1[u] ; i ; i = nex1[i] ) {
    		int v = tt1[i];
    		dfs1( v );
    	}
    	fwk::add( dfn[u] , -1 );
    }
    
    int main( ) {
    //	freopen("2.in","r",stdin);
    	scanf("%s",ch); n = strlen( ch );
    	for( int i = 0 ; i < n ; ++ i ) {
    		if( ch[i] == 'P' ) ins( zh , ++ cid ) , len = 0;
    		else if( ch[i] == 'B' ) {
    			if( len ) -- len;
    			else now = fa[now];
    		}
    		else zh[len ++] = ch[i];
    	}
    	build( );
    	dfs( 0 , 0 );
    	cin >> m;
    	for( int i = 1 , t , s ; i <= m ; ++ i ) 
    		scanf("%d%d",&t ,&s ) , ques[to[s]].push_back( make_pair( to[t] , i ) );
    	dfs1( 0 );
    //	sort( Q + 1 , Q + 1 + m , cmp );
    	for( int i = 1 ; i <= m ; ++ i ) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    月经贴——.net前景何妨!
    [Asp.net 5] Options-配置文件之后的配置
    [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)
    [Asp.net 5] Logging-其他日志系统的实现
    [Asp.net 5] Logging-日志系统的基本架构(下)
    [Asp.net 5] Logging-日志系统的基本架构(上)
    [Asp.net 5] Logging-新日志系统目录
    [Asp.net 5] Localization-简单易用的本地化
    [Asp.net 5] Localization-Asp.net运行时多语言
    java-多线程安全问题
  • 原文地址:https://www.cnblogs.com/yijan/p/12203215.html
Copyright © 2011-2022 走看看