boj1302
来源:互联网 发布:office for mac怎么样 编辑:程序博客网 时间:2024/06/01 11:22
Hard problemSubmit: 739 Accepted:199Time Limit: 4000MS Memory Limit: 200000K
Description
小明在读小学的时候实在是很贪玩,常常旷课跑出去玩,最后终于被老师给逮着了。老师可不会那么轻易地放过他,他得想个法子改改小明这坏习惯。刚好,老师知道小明的数学不好,然后想给他提高提高,怎么办呢?那就数数吧,老师也是个懂点电脑的人,他为了折腾小明,他随机生成了一个大串,然后叫小明去统计里边一些子串出现的次数,但是他怕小明眼花,所以字串的长度都不会超过8,但是取而代之的是会有大量的子串,当然子串可以有部分重叠。但是小明也不是一个笨小孩,他知道这些事情要他自己干的话也就十来二十年吧,不算太多,那也不少,所以他想请求在座的计算机大牛们帮帮他吧。
给一个由小写字母组成的字符串S 长度1<=L<=2^14 再给Q<200000次查询,每次查询都是一个字符串s长度1<=l<=8,要求找出给出的字符串s在S中出现的次数。
Input
多组数据测试
输入由3部分组成:
第一行为字符串S(字符串均由小写字母组成)
第二行为查询次数Q,
接下来为Q 行每行一个字符串.
Output
对应于每个查询的字符串输出此字符串在原字符串S中出现的次数.
Sample Input
ababababab
3
ab
aba
bab
accsafdac
1
ac
Sample Output
Case 1:
5
4
4
Case 2:
2
Source
dreamzk
来源:http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1302
trie树, 可以以查询串建树,以模式串进行查询,或者以模式串的所有长度小于8的字串建树, 每次查询。
第二种方法的代码:
struct Node
{
int cnt;
Node* next[26];
};
void init(Node* trie)
{
trie->cnt=0;
for(int i=0; i<26; i++)
trie->next[i]=NULL;
}
void insert(Node* root, char* str, int len)
{
Node* p = root;
int cur;
for(int i=0; i<len; i++, p=p->next[cur])
{
cur = str[i]-'a';
if(p->next[cur]==NULL)
{
p->next[cur]=new Node;
init(p->next[cur]);
}
}
p->cnt++;
}
int getCnt(Node* root, char* str)
{
int len = strlen(str);
Node* p = root;
int cur;
for(int i=0; i<len; i++)
{
cur = str[i]-'a';
if(p->next[cur]==NULL)
return 0;
p=p->next[cur];
}
return p->cnt;
}
void free(Node* root)
{
if(root==NULL)
return;
for(int i=0; i<26; i++)
free(root->next[i]);
delete root;
}
char str[(1<<14)+5];
char q[10];
int main()
{
Node *root;
int t=0;
while(scanf("%s", str)!=EOF)
{
int n;
root = new Node;
init(root);
int len = strlen(str);
for(int i=1; i<9; i++)
{
for(int j=0; j<len-i+1; j++)
insert(root, str+j, i);
}
scanf("%d", &n);
printf("Case %d:/n", ++t);
while(n--)
{
scanf("%s", q);
printf("%d/n", getCnt(root, q));
}
free(root);
}
return 0;
}