hdu 6096 String

  OvO http://acm.hdu.edu.cn/showproblem.php?pid=6096

  ( 2017 Multi-University Training Contest - Team 6 - 1001)

  对于n个串,构造新串。(构造方法:例如若串为ABCDE,构造新串为AEBDCCDBEA)、

  将新串插入到字典树(字典树每个节点存放一个vector)中,对于每个新串遍历到的节点,将原串的长度长度放入这些节点的vector中、

  将字典树每个节点的vector从小到大排序。

  对于询问的前后缀,类似地构造新串,空余出补*,(例如前缀ABC,后缀DEFGH,构造新串为AHBGCF*E*D)

  然后对于这些新串在字典树中进行询问,对于每个匹配到的节点,合法串的数量就是vector中保存的长度大于等于前缀后缀长度和的数字的数量。

  (思路来源于某大佬

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;

const int M=5e5+44;
const int N=1e5+44;

struct Node
{
	int len,pos;
};

queue<Node> que;

struct Trie
{
	const static int TRIE_M=1204000;
	const static int CHAR_SIZE=26;
	
	int root,tol,ch[TRIE_M][27];
	vector<int> tree[TRIE_M];
	
	int newnode()
	{
		tree[tol].clear();
		for(int i=0;i<26;i++)
			ch[tol][i]=-1;
		return tol++;
	}
	
	void init()
	{
		tol=0;
		root=newnode();
	}
	
	void insert(char strtmp[],int lentmp)
	{
//		cout<<"strtmp: "<<strtmp<<endl;
		int i,j;
		int now=root,nxt,valtmp;
		for(i=0;i<lentmp;i++)
		{
			valtmp=strtmp[i]-'a';
			if(ch[now][valtmp]==-1)
				ch[now][valtmp]=newnode(); 
			now=ch[now][valtmp];
			tree[now].push_back(lentmp/2);
//			cout<<"now: "<<now<<"  tree[now] size: "<<tree[now].size()<<endl;
		}
	}
	
	void build()
	{
		for(int i=0;i<tol;i++)
			sort(tree[i].begin(),tree[i].end());
	}
	
	int getval(int pos,int xlen)
	{
		int li=-1,ri=tree[pos].size(),mid;
//		cout<<"getval pos:"<<pos<<' '<<" size: "<<tree[pos].size()<<endl;
//		cout<<"detail val:"<<tree[pos][0]<<' '<<tree[pos][1]<<endl;
		while(li<ri-1)
		{
			mid=(li+ri)>>1;
			if(tree[pos][mid]<xlen)
				li=mid;
			else ri=mid;
		}
//		cout<<"li: "<<li<<endl;
		return tree[pos].size()-(li+1);
	}
	
	int query(char strtmp[],int lentmp,int xlen)
	{
		char chrtmp;
		int i,j,ret=0,pos,nxt;
		Node q,qq;
		while(!que.empty())
			que.pop();
		q.len=0; q.pos=0;
		que.push(q);
		while(!que.empty())
		{
			q=que.front(); que.pop();
			chrtmp=strtmp[q.len];
			pos=q.pos;
//			cout<<chrtmp<<' '<<pos;
//			if(chrtmp!='*')
//				cout<<"  ch[pos][chrtmp-'a']= "<<ch[pos][chrtmp-'a'];
//			cout<<endl;
			if(chrtmp=='*')
				for(i=0;i<26;i++)
				{
					nxt=ch[pos][i];
					if(nxt!=-1)
					{
						qq.len=q.len+1;
						qq.pos=nxt;
						if(qq.len==lentmp)
							ret+=getval(qq.pos,xlen);
						else que.push(qq);
					}
				}
			else
			{
				nxt=ch[pos][chrtmp-'a'];
				if(nxt!=-1)
				{
					qq.len=q.len+1;
					qq.pos=nxt;
					if(qq.len==lentmp)
						ret+=getval(qq.pos,xlen);
					else que.push(qq);
				}
			}	
		}
		return ret;
	}
} trie;

int n,q;
char strtmp[M],pretmp[M],suftmp[M],strget[M];

int main()
{
//	freopen("数据\\1001.in","r",stdin);
//	freopen("数据\\fxxl1001.out","w",stdout);
	int lentmp,prelen,suflen;
	int cas,i,j,ans;
	scanf("%d",&cas);
	while(cas--)
	{
		scanf("%d%d",&n,&q);
		trie.init();
		for(i=1;i<=n;i++)
		{
			scanf("%s",strtmp);
			lentmp=strlen(strtmp);
			for(j=0;j<lentmp;j++)
			{
				strget[j*2]=strtmp[j];
				strget[j*2+1]=strtmp[lentmp-1-j];
			}
			trie.insert(strget,lentmp*2);
		}
		trie.build();
		for(i=1;i<=q;i++)
		{
			scanf("%s%s",pretmp,suftmp);
			reverse(suftmp,suftmp+strlen(suftmp));
			prelen=strlen(pretmp); suflen=strlen(suftmp);
			lentmp=max(prelen,suflen);
			for(j=0;j<lentmp;j++)
			{
				if(j<prelen)
					strget[j*2]=pretmp[j];
				else strget[j*2]='*';
				if(j<suflen)
					strget[j*2+1]=suftmp[j];
				else strget[j*2+1]='*';
			}
			lentmp*=2;
			if(strget[lentmp-1]=='*') lentmp--;
			ans=trie.query(strget,lentmp,prelen+suflen);
			printf("%d\n",ans);
		}
	}
	return 0;
}

/*

1
4 1
aaaa
aaaaa
aaaaa
aa
aa aa

*/

  

转载于:https://www.cnblogs.com/FxxL/p/7346306.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值