大意:给定你一些商品的信息save(字符串),然后输入需要查询的字符串str,如果存在一个字符串save使得str是save的子串。
思路:字典树的变形,如存在"abcd",则"bcd", "cd", "d",都需要插入字典树中。如果存在"abab"的话,有可能"ab"会重复计数,所以需要一个特定的序列号来区分是否是同一序列中的子串。
我们可以定义一个value,若value相同,则跳过,若不同,则+1后更新value。
例如:假设总共有4个商品信息
5 5 5 5
a b a b
5 5 5
b a b
5 5
a b
5
b
4 4
a b
3 3
a b
2 2
a c
由上图可知,若序列号相同的话,则跳过。若不同,则+1,而且value需要更新避免后面的重复。
CODE:
#include <iostream>
#include <cstdio>
using namespace std;
struct Trie
{
Trie *next[26];
int count;
int value;
Trie()
{
for(int i = 0; i < 26; i++)
next[i] = 0;
count = 0;
value = 0;
}
};
void insert(Trie *&root, char *s, int num)
{
int i = 0, branch = 0;
Trie *p = root;
if(!p)
{
p = new Trie();
root = p;
}
while(s[i])
{
branch = s[i]-'a';
if(!p->next[branch]) p->next[branch] = new Trie();
p = p->next[branch];
if(p->value != num)
{
p->count++;
p->value = num;
}
i++;
}
}
int find(Trie *root, char *s)
{
int i = 0, branch = 0, ans;
Trie *p = root;
if(!p) return 0;
while(s[i])
{
branch = s[i]-'a';
if(!p->next[branch]) return 0;
p = p->next[branch];
ans = p->count;
i++;
}
return ans;
}
int main()
{
int Q;
scanf("%d", &Q);
char str[21];
Trie *root = NULL;
while(Q--)
{
scanf("%s", str);
for(int i = 0; i < strlen(str); i++)
insert(root, str+i, Q+1); //序列号
}
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", str);
printf("%d\n", find(root, str));
}
return 0;
}
#include <cstdio>
using namespace std;
struct Trie
{
Trie *next[26];
int count;
int value;
Trie()
{
for(int i = 0; i < 26; i++)
next[i] = 0;
count = 0;
value = 0;
}
};
void insert(Trie *&root, char *s, int num)
{
int i = 0, branch = 0;
Trie *p = root;
if(!p)
{
p = new Trie();
root = p;
}
while(s[i])
{
branch = s[i]-'a';
if(!p->next[branch]) p->next[branch] = new Trie();
p = p->next[branch];
if(p->value != num)
{
p->count++;
p->value = num;
}
i++;
}
}
int find(Trie *root, char *s)
{
int i = 0, branch = 0, ans;
Trie *p = root;
if(!p) return 0;
while(s[i])
{
branch = s[i]-'a';
if(!p->next[branch]) return 0;
p = p->next[branch];
ans = p->count;
i++;
}
return ans;
}
int main()
{
int Q;
scanf("%d", &Q);
char str[21];
Trie *root = NULL;
while(Q--)
{
scanf("%s", str);
for(int i = 0; i < strlen(str); i++)
insert(root, str+i, Q+1); //序列号
}
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", str);
printf("%d\n", find(root, str));
}
return 0;
}