算法练习:Trie树
问题:没弄懂这道题题目的输入格式,我自己写的输入方式SF
#include<iostream>
#include<string>
using namespace std;
const int N=500010;
//son用来记录所有节点的儿子节点,cnt记录每个节点以该节点结尾的字符串个数,pass记录字符串经过该节点的数量
int son[N][2],cnt[N],pass[N],idx=0;
//创建加密信息的字符串的trie树
void insert(string s)
{
int p=0;
int len=s.size();
for(int i=0;i<len;i++)
{
int u=s[i]-'0';
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
pass[p]++; //记录经过该节点的数量
}
cnt[p]++; //记录该最后一个字母在该节点结尾的字符串数量
}
//在加密信息树中查询传入的解密信息可能跟它们匹配的数量(可能解密信息的字符串长度大于加密信息字符串长度,也可能加密信息字符串长度大于解密信息字符串长度)
int query(string s)
{
int p=0;
int sum=0; //记录查询解密字符串过程中累加的cnt[p],即就是加密字符串长度小于解密字符串长度,所有解密字符串中为该加密字符串前缀的数量和
int len=s.size();
for(int i=0;i<len;i++)
{
int u=s[i]-'0';
if(!son[p][u]) return sum; //当解密字符串中的字符已经匹配完所有可匹配的加密字符串(加密字符串长度小于解密字符串长度,解密字符串为加密字符串前缀)
//解密字符串中字符还可以接下去匹配加密树中字符
p=son[p][u];
sum+=cnt[p];
}
//解密字符全部在加密树中匹配完成(加密字符创长度大于解密字符串长度,解密字符创长度是加密字符串前缀)
return sum+pass[p]-cnt[p];
//返回结果要多加上一个pass[p]-cnt[p]
//pass[p]是经过该解密字符串最后一个字母的数量(即所有包含(可等于)该解密字符串的数量
//减去cnt[p]就是减去加密树中以该字符为结尾的字符串(等于该解密字符串)的数量,那剩下的就是解密字符串为加密串字符串前缀的数量
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
while(n--)
{
int k;
string s;
cin>>k;
for(int j=1;j<=k;j++)
{
char c;
cin>>c;
s+=c;
}
insert(s);
}
while(m--)
{
int k;
string s;
cin>>k;
for(int j=1;j<=k;j++)
{
char c;
cin>>c;
s+=c;
}
printf("%d\n",query(s));
}
return 0;
}