zoukankan      html  css  js  c++  java
  • Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】

    正题

    题目链接:https://ac.nowcoder.com/acm/contest/72/F


    题目大意

    (n)个字符串,包括小写字母和(#)。其中(#)可以替换为任意字符串。求有多少对字符串可能相同。

    保证每个字符串至少有一个(#)

    (2leq nleq 500000,sum_{i=1}^n |s_i|leq 10^6)


    解题思路

    因为可以替换为任意字符串,所以只需要考虑第一个(#)前和最后一个(#)后的部分。

    在仔细考虑一下,这个字符串分成前后的两个部分(s,t)。数对((x,y))满足条件当且仅当(s_x)(s_y)的前缀,或者(s_y)(s_x)的前缀,且(t_x)(t_y)的后缀,或者(t_y)(t_x)的后缀。

    放到两棵(Trie)树上就是都有祖先关系就好了,直接跑第一棵上,然后用两个树状数组在第二棵树上维护就好了。

    时间复杂度(O(mlog m))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define lowbit(x) (x&-x)
    using namespace std;
    const int N=1e6+10;
    int n,cnt,pos[N],dfn[N],ed[N];
    long long ans;char s[N];
    vector<int> G[N]; 
    struct TreeBinary{
    	int t[N];
    	void Change(int x,int val){
    		while(x<=cnt){
    			t[x]+=val;
    			x+=lowbit(x);
    		}
    		return;
    	}
    	int Ask(int x){
    		int ans=0;
    		while(x){
    			ans+=t[x];
    			x-=lowbit(x);
    		}
    		return ans;
    	}
    }Bf,Bs;
    struct Trie{
    	int t[N][26],m=1;
    	int Insert(char *s,int n){
    		int x=1;
    		for(int i=1;i<=n;i++){
    			if(s[i]=='#')break;
    			int c=s[i]-'a';
    			if(!t[x][c])t[x][c]=++m;
    			x=t[x][c];
    		}
    		return x;
    	}
    }Tp,Ts;
    void dfs(int x){
    	dfn[x]=++cnt;
    	for(int i=0;i<26;i++)
    		if(Ts.t[x][i])
    			dfs(Ts.t[x][i]);
    	ed[x]=cnt;
    }
    void work(int x){
    	for(int i=0;i<G[x].size();i++){
    		int p=G[x][i];ans+=Bf.Ask(dfn[pos[p]]);
    		Bf.Change(dfn[pos[p]],1);Bf.Change(ed[pos[p]]+1,-1);
    		ans+=Bs.Ask(ed[pos[p]])-Bs.Ask(dfn[pos[p]]); 
    		Bs.Change(dfn[pos[p]],1);
    	}
    	for(int i=0;i<26;i++)
    		if(Tp.t[x][i])
    			work(Tp.t[x][i]);
    	for(int i=0;i<G[x].size();i++){
    		int p=G[x][i];Bs.Change(dfn[pos[p]],-1);
    		Bf.Change(dfn[pos[p]],-1);Bf.Change(ed[pos[p]]+1,1);
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",s+1);
    		int l=strlen(s+1);
    		int x=Tp.Insert(s,l);
    		G[x].push_back(i);
    		reverse(s+1,s+1+l);
    		pos[i]=Ts.Insert(s,l);
    	}
    	dfs(1);
    	work(1);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    coredata
    去除XIB上UITextView光标垂直居中问题
    IOS 开发使用SVN
    CSS层叠样式表--找到标签
    简单的爬虫
    HTML
    13索引
    12事务
    12内建函数
    11存储过程
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15163944.html
Copyright © 2011-2022 走看看