前言
你有好多好多字符串,还有好多好多要查询的字符串,你要确定要查询的字符串是否出现过,如果使用暴力搜索,那么肯定爆炸了,那么这样我们该如何进行查找呢?
如果要存:"abc"、"bc"、"bd"、"cd"的话
那么代码怎么写呢?
1.存储
如果用数组存,我们就需要一个二维数组a[n][m]。n点的标号,定义时设为字符串的总长,m指字符类型,定义时设为字符类型总数。
2.添加
首先需要一个记录点编号的ptop,在添加时,先从ROOT,即从a[0]开始找,如果a[查找编号][查找字符编号]存在则继续找,不存在则令其等于++ptop,然后从ptop继续找。
void add(char str[])
{
int p = 0,end = strlen(str);
for(int i = 0;i < end;i++)
{
if(a[p][turn(str[i])] == 0)
p = a[p][turn(str[i])] = ++ptop;
else
p = a[p][turn(str[i])];
}
}
3.查找数量
定义一个cnt[n]来记录,如果是前缀就让加入时便cnt[p]++,如果是单词数量便在最后cnt[p]++即可,查找就正常查找。
输出:
int find(char str[])
{
int end = strlen(str);
int p = 0;
for(int i = 0;i < end;i++)
{
p = a[p][turn(str[i])];
if(p == 0)
return 0;
}
return cnt[p];
}
4.字符转数字
我们需要一个turn函数让字符转成对应的编号
代码:
const int MAXN = 3e6 + 10;
int turn(char c)
{
if(c >= 'a' && c <= 'z')
return c - 'a';
else if(c >= 'A' && c <= 'Z')
return c - 'A' + 26;
else
return c - '0' + 52;
}
struct tiretree{
int ptop = 0;
int a[MAXN][70];
int cnt[MAXN];
void clear()
{
for(int i = 1;i <= ptop;i++)
{
cnt[i] = 0;
for(int j = 0;j <= 69;j++)
a[i][j] = 0;
}
ptop = 0;
}
void add(char str[])
{
int p = 0,end = strlen(str);
for(int i = 0;i < end;i++)
{
if(a[p][turn(str[i])] == 0)
p = a[p][turn(str[i])] = ++ptop;
else
p = a[p][turn(str[i])];
cnt[p]++;
}
}
int find(char str[])
{
int end = strlen(str);
int p = 0;
for(int i = 0;i < end;i++)
{
p = a[p][turn(str[i])];
if(p == 0)
return 0;
}
return cnt[p];
}
}ttree;