2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

paiza×Qiita記事投稿キャンペーンということで、paizaラーニングレベルアップ問題集の文字列収集をやってみました。


入力の後半でクエリ文字列が来てから市場に出回っている$N$個の文字列を精査していては、時間がかかりすぎてしまいます。予め、このクエリ文字列が来たら必要金額はいくら、ということを計算しておきましょう。クエリ文字列と必要金額は、連想配列に格納しておきます。(下の表の、太字の入力に対して、細字の文字列と数値を格納。同じ文字列(キー)が来たら数値を足し合わせる)

bcac 3
b 3
bc 3
bca 3
bcac 3
#include <iostream>
#include <map>
#include <utility>
using namespace std;

int main() {
	int n, m;
	cin >> n >> m;
	map<string, int> dict;
	for (int i = 0; i < n; i++) {
		string s;
		int p;
		cin >> s >> p;
		for (int j = 1; j <= s.size(); j++) {
			dict[s.substr(0, j)] += p; //s.substr(0,j)がdictに登録されていない場合はdict[s.substr(0,j)]に0+pが格納される。
		}
	}
	for (int i = 0; i < m; i++) {
		string q;
		cin >> q;
		cout << dict[q] << endl;
	}
	return 0;
}

C++のmapは、連想配列に登録されていないキーに対する値を求めようとしたとき、デフォルト値が返されます(値がint型の場合は0)。Pythonのdefaultdictも同様です。しかし、多くの言語では、連想配列に登録されていないキーに対する値を求めようとするとエラーになりますので、既にキーが登録されている/されていないでチェック&分岐処理が必要になります。


以上で終わりなのですが、トライ木というものを使って実装してみましょう。よく分からないという方は、リンク先やタグ遷移先を参照してください。
トライ木メニューを参考にしてトライ木を実装してみます。今回は、この問題を解けるように改変しています。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
	int value; //合計必要金額
	struct Node *child[26];
} Node;

typedef struct Trie {
	Node *root;
} Trie;

void insert(Trie *trie, const char *key, int value) {
	Node *node = trie->root;
	for (const char *c = key; *c; c++) {
		int ch = (int) (*c - 'a');
		if (!node->child[ch]) {
			if (!(node->child[ch] = (Node*) malloc(sizeof(Node)))) {
				abort();
			}
			memset(node->child[ch], 0, sizeof(Node));
		}
		node->child[ch]->value += value;
		node = node->child[ch];
	}
}

int search(const Trie *trie, const char *key) {
	Node *node = trie->root;
	for (const char *c = key; *c; c++) {
		int ch = (int) (*c - 'a');
		if (!node->child[ch]) {
			return 0;
		}
		node = node->child[ch];
	}
	return node->value;
}

void _clear(Node *node) {
	for (char c = 'a'; c <= 'z'; c++) {
		if (node->child[c - 'a']) {
			_clear(node->child[c - 'a']);
		}
	}
	free(node);
}

void clear(Trie *trie) {
	_clear(trie->root);
	trie->root = NULL;
}

上のトライ木を用いて、問題を解いていきます。

int main() {
	int n, m;
	scanf("%d %d", &n, &m);

	Trie trie;
	trie.root = (Node*) malloc(sizeof(Node));
	memset(trie.root, 0, sizeof(Node));
	for (int i = 0; i < n; i++) {
		char s[101];
		int p;
		scanf("%s %d", s, &p);
		insert(&trie, s, p);
	}
	for (int i = 0; i < m; i++) {
		char q[101];
		scanf("%s", q);
		printf("%d\n", search(&trie, q));
	}
	clear(&trie);
	return 0;
}

問題文の入力例1では、まず、以下のようにトライ木に格納されます。
bcac 3

abcd 14

abccjg 92

bcaddgie 2

abcd 6

cd 200


そして、以下のように値を取り出していきます。丸ノードの値が答えです。
b


a


abcd


gagioheo

gagioheoで始まる単語は格納されていませんので、0が答えです。


cb

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?