尝试着不看别人的代码自己打了一遍,结果发现有很多可以优化的地方。
略(没有为什么)
#include<bits/stdc++.h>
using namespace std;
const int N = 3000000 + 5;
int cnt = 1, son[N], bro[N], num[N], lgh[N];
char info[N][15];
char tmp[15];
int len;
inline void split (int u, int v) {
cnt++;
for (int i = v + 1; i <= lgh[u]; ++i) {
info[cnt][i - v] = info[u][i];
}
lgh[cnt] = lgh[u] - v;
lgh[u] = v;
son[cnt] = son[u];
son[u] = cnt;
num[cnt] = num[u];
num[u] = 0;
}
inline void insert (int u, int p) {
while (1) {
for (int i = son[p]; i != -1; i = bro[i]) {
if (info[i][1] == tmp[u + 1]) {
for (int j = 2; j <= min (lgh[i], len - u); ++j) {
if (info[i][j] != tmp[u + j]) {
j--;
split (i, j);
int now = son[i];
cnt++;
bro[now] = cnt;
for (int k = u + j + 1; k <= len; ++k) {
info[cnt][k - (u + j)] = tmp[k];
}
lgh[cnt] = len - (u + j);
num[cnt] = 1;
return ;
}
}
if (lgh[i] == len - u) {
num[i]++;
return ;
}
else if (lgh[i] < len - u) {
u += lgh[i];
p = i;
goto next;
}
}
}
cnt++;
bro[cnt] = son[p];
son[p] = cnt;
for (int i = u + 1; i <= len; ++i) {
info[cnt][i - u] = tmp[i];
}
lgh[cnt] = len - u;
num[cnt] = 1;
return ;
next:;
}
}
void dfs (int u) {
for (int i = son[u]; i != -1; i = bro[i]) {
dfs (i);
num[u] += num[i];
}
}
inline int query (int u, int p) {
while (1) {
for (int i = son[p]; i != -1; i = bro[i]) {
if (info[i][1] == tmp[u + 1]) {
for (int j = 2; j <= min (lgh[i], len - u); ++j) {
if (info[i][j] != tmp[u + j]) {
return 0;
}
}
if (lgh[i] >= len - u) {
return num[i];
}
else {
p = i;
u += lgh[i];
goto next;
}
}
}
return 0;
next:;
}
}
int main () {
memset (son, -1, sizeof (son));
memset (bro, -1, sizeof (bro));
while (1) {
gets (tmp + 1);
if (!tmp[1]) {
break;
}
len = strlen (tmp + 1);
tmp[++len] = 'X';
insert (0, 1);
}
dfs (1);
while (scanf ("%s", tmp + 1) == 1) {
len = strlen (tmp + 1);
printf ("%d\n", query (0, 1));
}
return 0;
}
#include <iostream>
#include <stdio.h>
using namespace std;
int trie[1000010][26]; //数组形式定义字典树,值存储的是下一个字符的位置
int num[1000010]={0}; //附加值,以某一字符串为前缀的单词的数量
int pos = 1;
void Insert(char word[]) //在字典树中插入某个单词
{
int i;
int c = 0;
for(i=0;word[i];i++){
int n = word[i]-'a';
if(trie[c][n]==0) //如果对应字符还没有值
trie[c][n] = pos++;
c = trie[c][n];
num[c]++;
}
}
int Find(char word[]) //返回以某个字符串为前缀的单词的数量
{
int i;
int c = 0;
for(i=0;word[i];i++){
int n = word[i]-'a';
if(trie[c][n]==0)
return 0;
c = trie[c][n];
}
return num[c];
}
int main()
{
char word[11];
while(gets(word)){
if(word[0]==NULL) //空行。gets读入的回车符会自动转换为NULL。
break;
Insert(word);
}
while(gets(word))
printf("%d\n",Find(word));
return 0;
}
第二个代码摘自https://www.cnblogs.com/yym2013/p/3780621.html
暂无。
原文:https://www.cnblogs.com/ChiTongZ/p/11197594.html