题目大意:
题目链接:https://www.luogu.org/problemnew/show/P2922
给出个01串,再给出个01串,求对于每一个串,有多少串和这个串有相同的前缀。
思路:
这道题考。
对于每一个结点,最多有两个子节点(0和1),那么可以先把所有串插入到里,然后对于每一个串,我们在里面匹配,当两种情况时结束:
- 当无法再往下匹配时(没有子结点了)。此时可以直接输出答案。
- 当长度不够期且下面还有结点时。此时答案为。因为有还有个串经过这个结点,所以就有个串的前缀和它的前缀一样。
代码:
#include <cstdio>
using namespace std;
int n,m,k,ans,a[50011],sum[500011],end[500011],tot=1,trie[500001][2];
void insert(int len) //插入
{
int p=1;
for (int i=1;i<=len;i++)
{
if (!trie[p][a[i]]) trie[p][a[i]]=++tot; //新建节点
p=trie[p][a[i]];
sum[p]++; //经过该结点的串的个数
}
end[p]++; //结束位置
}
void find(int len) //查找
{
int p=1;
for (int i=1;i<=len;i++)
{
if (!trie[p][a[i]]) //没得往下找了
{
printf("%d\n",ans);
return;
}
p=trie[p][a[i]];
ans+=end[p]; //加上答案
}
printf("%d\n",ans-end[p]+sum[p]);
return;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&k);
for (int j=1;j<=k;j++)
scanf("%d",&a[j]);
insert(k);
}
for (int i=1;i<=m;i++)
{
scanf("%d",&k);
for (int j=1;j<=k;j++)
scanf("%d",&a[j]);
ans=0;
find(k);
}
return 0;
}