【Trie】JZOJ_3126 大LCP

题意

给出一些字符串,有q次询问,问前k个字符串中两两之间的最大的LCP(最长公共前缀)。

思路

因为是前k个,我们就可以用一个数组来记录。把每次读入的字符串存进字典树里,在放进字典树的过程中我们可以很容易地计算出它和之前的字符串的LCP,然后和前面的比较就好了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,q,tot=1,trie[1000001][26],a,lcp[100001],x,f,tj,l;//trie[i][j]表示节点i的j字符指向的节点
char s[1000001];
int insert()
{
	scanf("%s",s+1);
	int x=1,f=1,tj=0,l=strlen(s+1);//这里我没有设l的话好像会超时
	for (int i=1;i<=l;i++)
	{
		if (!trie[x][s[i]-'a']) {f=0;trie[x][s[i]-'a']=++tot;}//之前没有插入过我们就新开一个点,并且更新f
		x=trie[x][s[i]-'a'];//跳
		tj+=f;//如果当前字符串已经和之前的没有匹配了那么f会改成0,这里就没有累加LCP了
	}
	return tj;
}
int main()
{
	scanf("%d%d",&n,&q);
	for (int i=1;i<=n;i++) 
		lcp[i]=max(insert(),lcp[i-1]);
	while (q--)
	{
		scanf("%d",&a);
		printf("%d\n",lcp[a]);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值