hdu 2846 Repository 字典树

//	hdu 2846 Repository 字典树
//
//	题目大意:
//
//		有n个字符串,m个待询问的字符串,问这些字符串里面以该询问的
//		字符串为子串的字符串有多少个
//
//	解题思路:
//
//		字典树,将字符串的所有子串插入到字典树中,并设立一个No.标识
//		以免重计数。最后查询就好了
//
//	感悟:
//
//		这题的数据量有点大,虽然p是10000,但是长度是20,单个字符串的
//		最大子串数粗略的估计是 20 * 20 ,所以开的空间也要比较大。开始
//		开的是30w,返回了wa,开了40w,还是返回wa,开了50w,结果轻松Ac
//		啦~,继续加油哟~~~FIGHTING

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX_N = 500000;

struct Trie{

	int ch[MAX_N][26];
	int sz;
	int val[MAX_N];
	int no[MAX_N];

	void init(){
		sz = 1;
		memset(ch[0],0,sizeof(ch[0]));
		val[0] = 0;
		no[0] = 0;
	}

	int idx(char c){
		return c - 'a';
	}

	void insert(char *s,int st,int ed,int v){
		int u = 0;
		//int n = strlen(s);
		for (int i=st;i<=ed;i++){
			int c = idx(s[i]);

			if (no[u]!=v)	// 这里是为了不重复计数,如果插入的点
				val[u]++;   // 是当前的串的子串,所有的该串子串都
							// 会有特定的v的标记,碰到了就避免计数

			if (!ch[u][c]){
				memset(ch[sz],0,sizeof(ch[sz]));
				val[sz] = 0;
				no[sz] = 0;
				ch[u][c] = sz++;
			}
			u = ch[u][c];
		}
		if (no[u]!=v)  // 不要忘了在插入的末尾,可能还会有相同的子串诺
			val[u]++;
		no[u] = v;
	}

	int query(char *s){
		int u = 0;
		int n = strlen(s);
		for (int i=0;i<n;i++){
			int c = idx(s[i]);
			if (!ch[u][c]){
				return 0;
			}

			u = ch[u][c];
		}
		return val[u];
	}

}trie;

void print(char *s,int st,int ed,int num){
	printf("%d \n\n",num);
	for (int i=st;i<=ed;i++){
		printf("%c",s[i]);
	}
	cout << endl;
}

int n,m;
bool vis[10009];
void input(){
	trie.init();
	char s[30];
	for (int i=1;i<=n;i++){
		scanf("%s",s);
		int len = strlen(s);
		for (int j=len-1;j>=0;j--){
			for (int k=j;k<len;k++){
				trie.insert(s,j,k,i);
				//print(s,j,k,i);
			}
		}
	}
	scanf("%d",&m);
	for (int i=1;i<=m;i++){
		scanf("%s",s);
		printf("%d\n",trie.query(s));

	}

	//memset(vis,0,sizeof(vis))

}

int main(){
	//freopen("1.txt","r",stdin);
	while(scanf("%d",&n)!=EOF){
		input();
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 16:15:40

hdu 2846 Repository 字典树的相关文章

HDU 2846 Repository(字典树,标记)

题目 字典树,注意初始化的位置~!!位置放错,永远也到不了终点了org.... 我是用数组模拟的字典树,这就要注意内存开多少了,,要开的不大不小刚刚好真的不容易啊.... 我用了val来标记是否是同一个串分解而来的,保存的是串的编号 num记录数目. //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[firs

HDU 2846 Repository (字典树 后缀建树)

Repository Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2932    Accepted Submission(s): 1116 Problem Description When you go shopping, you can search in repository for avalible merchandises

hdu 2846 Repository 字典树的一种变形

Repository Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2633    Accepted Submission(s): 1028 Problem Description When you go shopping, you can search in repository for avalible merchandises

HDU 1247 简单字典树

Hat’s Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7359    Accepted Submission(s): 2661 Problem Description A hat’s word is a word in the dictionary that is the concatenation of exactly

HDU 2846 Repository(字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 题目:输入个n个词典串,然后输入q个串,对这q个串分别输出每个串都是几个词典串的子串. 思路:因为要包含子串,比如abd,将串abd,bd,d都插入字典树,然后每个节点下统计子树个数,直接查找前缀就可以了.但需要注意dcda这种的,需要插入dcda,cda,da,a,这个时候d下面的子树应该是一个而不是2个,因为dcda和da属于同一个词典串.所以在插入的时候进行处理即可. 代码 #inclu

hdu 1979 DFS + 字典树剪枝

http://acm.hdu.edu.cn/showproblem.php?pid=1979 Fill the blanks Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 373    Accepted Submission(s): 155 Problem Description There is a matrix of 4*4, yo

hdu 1298 T9(字典树+DFS)

题目连接:hdu 1298 T9 题目大意:模拟手机打字的猜想功能,根据概率,每按一个按键,输出可能性最高的串.先给定N个单词,以及频率, 然后是Q次询问,每次询问给定一个按按键的顺序,以1为终止. 解题思路:对单词表建立字典树,每个节点有一个经过的频率,这个频率是根据所有经过该节点的单词频率总和.然后 DFS搜索一遍,将答案保存在ans中. #include <cstdio> #include <cstring> #include <algorithm> using

HDU 1671 (字典树统计是否有前缀)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1671 Problem Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers: 1. Emergenc

[HDU] 4825 (01字典树)

Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Input 输入包含若干组测试数据,每组测试数据