zoukankan      html  css  js  c++  java
  • HDU6069 String

    题目

    Bob has a dictionary with N words in it.
    Now there is a list of words in which the middle part of the word has continuous letters disappeared. The middle part does not include the first and last character.
    We only know the prefix and suffix of each word, and the number of characters missing is uncertain, it could be 0. But the prefix and suffix of each word can not overlap.
    For each word in the list, Bob wants to determine which word is in the dictionary by prefix and suffix.
    There are probably many answers. You just have to figure out how many words may be the answer.

    大意是给你一个前缀一个后缀,问能够同时满足这个前缀和后缀的串有多少个。

    思路

    这里有一个非常巧妙的处理方法,一般很难想到:把待匹配的串T转化为T+'{'+T的形式,把前缀s1和后缀s2转化为s2+'{'+s1的形式。这样就把原问题转化为了一个普通的字符串匹配问题,只要dfs一遍fail树,把子树信息统计上来就行了。

    然而,注意题目中还有一个限制条件:前缀后缀不能重叠,也就意味着我们还要维护一维信息。

    所以只要把这一维用树状数组,然后dfs作差就好了。

    代码

    #include<bits/stdc++.h>
    #define M 1000005
    #define clr(x,y) memset(x,y,sizeof(x))
    using namespace std;
    int T,n,q,ans[M];
    char S[M],wk[M<<1];
    char S1[M],S2[M];
    int h[M],tot;
    struct que{int id,l;};
    vector<que>Q[M];
    int pre[M];
    struct edge{
    	int nxt,to;
    }G[M<<1];
    void Add(int a,int b){
    	G[++tot]=(edge){h[a],b};
    	h[a]=tot;	
    }
    struct BIT{
    	int C[M];
    	void clear(){
    		clr(C,0);	
    	}
    	void add(int x,int d){
    		x++;
    		while(x<M){
    			C[x]+=d;
    			x+=(x&-x);	
    		}
    	}
    	int sum(int x){
    		int res=0;
    		x++;
    		while(x){
    			res+=C[x];
    			x-=(x&-x);
    		}
    		return res;
    	}
    }TT;
    struct AC_automaton{
    	int tt;
    	int pa[M][27];
    	int f[M];
    	vector<int>val[M];
    	void clear(){
    		clr(pa[0],0);
    		clr(f,0);
    		for(int i=0;i<=tt;i++)val[i].clear();
    		tt=0;
    	}
    	int Insert(char *S,int d){
    		int u=0,l=strlen(S);
    		for(int i=0;i<l;i++){
    			int c=S[i]-'a';
    			if(!pa[u][c]){
    				pa[u][c]=++tt;
    				clr(pa[tt],0);
    				Q[tt].clear();
    			}
    			u=pa[u][c];
    			if(d!=-1)val[u].push_back(d);
    		}
    		return u;
    	}
    	void get_fail(){
    		queue<int>Q;
    		for(int i=0;i<=26;i++){
    			if(pa[0][i]!=0){
    				f[pa[0][i]]=0;
    				Q.push(pa[0][i]);	
    			}
    		}
    		while(!Q.empty()){
    			int u=Q.front();Q.pop();
    			for(int i=0;i<=26;i++){
    				if(pa[u][i]!=0){
    					f[pa[u][i]]=pa[f[u]][i];
    					Q.push(pa[u][i]);
    				}
    				else pa[u][i]=pa[f[u]][i];
    			}
    		}
    		for(int i=1;i<=tt;i++)if(f[i]!=i)Add(f[i],i);
    	}
    }Tr;
    void jie(char *s1,char *s2,char *s3){
    	int l1=strlen(s1);
    	int l2=strlen(s2);
    	int l3=0;
    	for(int i=0;i<l1;i++)s3[l3++]=s1[i];
    	s3[l3++]='{';
    	for(int i=0;i<l2;i++)s3[l3++]=s2[i];
    }
    int find(char *s){
    	int l=strlen(s),u=0;
    	for(int i=0;i<l;i++){
    		if(!Tr.pa[u][s[i]-'a'])return -1;
    		u=Tr.pa[u][s[i]-'a'];
    	}
    	return u;
    }
    void dfs(int x){
    	for(int i=0;i<Q[x].size();i++)
    		pre[Q[x][i].id]=TT.sum(M-1)-TT.sum(Q[x][i].l-1);
    	for(int i=0;i<Tr.val[x].size();i++)
    		TT.add(Tr.val[x][i],1);
    	for(int i=h[x];i;i=G[i].nxt)dfs(G[i].to);
    	for(int i=0;i<Q[x].size();i++)
    		ans[Q[x][i].id]=TT.sum(M-1)-TT.sum(Q[x][i].l-1)-pre[Q[x][i].id];
    }
    int main(){
    	cin>>T;
    	while(T--){
    		Tr.clear();clr(h,0);tot=0;
    		TT.clear();clr(ans,0);
    		scanf("%d%d",&n,&q);
    		for(int i=1;i<=n;i++){
    			scanf("%s",S);
    			int l=strlen(S);
    			jie(S,S,wk);
    			wk[l+l+1]=0;
    			Tr.Insert(wk,strlen(S));
    		}
    		for(int i=1;i<=q;i++){
    			scanf("%s%s",S1,S2);
    			jie(S2,S1,wk);
    			wk[strlen(S1)+strlen(S2)+1]=0;
    			int k=Tr.Insert(wk,-1);
    			if(k==-1)ans[i]=0;
    			else Q[k].push_back((que){i,strlen(wk)-1});
    		}
    		Tr.get_fail();
    		dfs(0);
    		for(int i=1;i<=q;i++)
    			printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    产品开发管理之流程和体系(总篇)
    .NET Core工程编译事件$(TargetDir)变量为空引发的思考
    EF Core新增迁移时无法加载程序集“System.ValueTuple”的错误
    Magicodes.Admin.Core开源框架总体介绍
    在WIN SERVER 2016上安装DOCKER(带过坑)
    使用NPOI生成Excel级联列表
    使用批处理根据项目工程文件生成Nuget包并发布(支持.NET Core)
    C#反射
    Oracle创建库
    深入了解MyBatis参数
  • 原文地址:https://www.cnblogs.com/zryabc/p/10467531.html
Copyright © 2011-2022 走看看