forked from harrypotter0/algorithms-in-python
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
74713f8
commit 1d147f5
Showing
2 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#include <bits/stdc++.h> | ||
using namespace std; | ||
|
||
typedef long long lint; typedef pair<int, int> ii; | ||
const int MOD = 1'000'000'007, MOD2 = 1'000'000'009; | ||
const int INF = 0x3f3f3f3f; const lint BINF = 0x3f3f3f3f3f3f3f3fLL; | ||
|
||
struct StringTrie{ | ||
|
||
StringTrie *chi[26]; | ||
int dat; | ||
|
||
StringTrie(){ | ||
for(int i=0;i<26;i++) chi[i] = nullptr; | ||
dat = -1; | ||
} | ||
|
||
StringTrie(StringTrie *old){ | ||
for(int i=0;i<26;i++) chi[i] = old->chi[i]; | ||
dat = old->dat; | ||
} | ||
|
||
StringTrie *set(string &s, int val, int pos = 0){ | ||
StringTrie *rt = new StringTrie(this); | ||
if(pos >= s.size()){ | ||
//printf("choot1\n", ); | ||
rt->dat = val; | ||
}else{ | ||
//printf("choot2\n", ); | ||
int v = s[pos] - 'a'; | ||
if(!chi[v]) chi[v] = new StringTrie(); | ||
rt->chi[v] = chi[v]->set(s, val, pos + 1); | ||
} | ||
return rt; | ||
} | ||
|
||
int get(string &s, int pos = 0){ | ||
if(pos >= s.size()){ | ||
return dat; | ||
}else{ | ||
int v = s[pos] - 'a'; | ||
if(!chi[v]) return -1; | ||
return chi[v]->get(s, pos + 1); | ||
} | ||
} | ||
|
||
}; | ||
|
||
struct BinaryTrie{ | ||
|
||
BinaryTrie *chi[2]; | ||
int dat; | ||
|
||
BinaryTrie(){ | ||
chi[0] = chi[1] = nullptr; | ||
dat = 0; | ||
} | ||
|
||
BinaryTrie(BinaryTrie *old){ | ||
chi[0] = old->chi[0]; | ||
chi[1] = old->chi[1]; | ||
dat = old->dat; | ||
} | ||
|
||
BinaryTrie *add(int s, int val, int pos = 30){ | ||
BinaryTrie *rt = new BinaryTrie(this); | ||
rt->dat += val; | ||
if(pos >= 0){ | ||
int v = (s >> pos) & 1; | ||
if(!chi[v]) chi[v] = new BinaryTrie(); | ||
rt->chi[v] = chi[v]->add(s, val, pos - 1); | ||
} | ||
return rt; | ||
} | ||
|
||
int get(int s, int pos = 30){ | ||
if(pos < 0){ | ||
return 0; | ||
}else{ | ||
int v = (s >> pos) & 1; | ||
if(v){ | ||
int ans = 0; | ||
// add 0 | ||
if(chi[0]) ans += chi[0]->dat; | ||
// query 1 | ||
if(chi[1]) ans += chi[1]->get(s, pos - 1); | ||
return ans; | ||
}else{ | ||
// query 0 | ||
if(chi[0]) | ||
return chi[0]->get(s, pos - 1); | ||
else | ||
return 0; | ||
} | ||
} | ||
} | ||
|
||
}; | ||
|
||
int solve(){ | ||
int q; cin >> q; | ||
StringTrie **st = new StringTrie*[q + 5]; | ||
BinaryTrie **bt = new BinaryTrie*[q + 5]; | ||
st[0] = new StringTrie(); | ||
bt[0] = new BinaryTrie(); | ||
for(int i=1;i<=q;i++){ | ||
string op; cin >> op; | ||
if(op == "set"){ | ||
string str; int val; | ||
cin >> str >> val; | ||
int x = st[i-1]->get(str); | ||
st[i] = st[i-1]->set(str, val); | ||
if(x >= 0){ | ||
bt[i] = bt[i-1]->add(x, -1); | ||
bt[i] = bt[i]->add(val, 1); | ||
}else{ | ||
bt[i] = bt[i-1]->add(val, 1); | ||
} | ||
}else if(op == "remove"){ | ||
string str; cin >> str; | ||
int x = st[i-1]->get(str); | ||
st[i] = st[i-1]->set(str, -1); | ||
if(x >= 0) | ||
bt[i] = bt[i-1]->add(x, -1); | ||
else | ||
bt[i] = bt[i-1]; | ||
}else if(op == "undo"){ | ||
int x; cin >> x; | ||
st[i] = st[i - x - 1]; | ||
bt[i] = bt[i - x - 1]; | ||
}else{ | ||
st[i] = st[i - 1]; | ||
bt[i] = bt[i - 1]; | ||
string str; cin >> str; | ||
int x = st[i]->get(str); | ||
if(x >= 0) | ||
cout << bt[i]->get(x) << endl; | ||
else | ||
cout << -1 << endl; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
int main(){ | ||
ios::sync_with_stdio(0); | ||
// int t; cin >> t; while(t--) | ||
solve(); | ||
// cout << (solve() ? "YES" : "NO") << endl; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
#include <iostream> | ||
|
||
// define character size | ||
#define CHAR_SIZE 128 | ||
|
||
// A Class representing a Trie node | ||
class Trie | ||
{ | ||
public: | ||
bool isLeaf; | ||
Trie* character[CHAR_SIZE]; | ||
|
||
// Constructor | ||
Trie() | ||
{ | ||
this->isLeaf = false; | ||
|
||
for (int i = 0; i < CHAR_SIZE; i++) | ||
this->character[i] = nullptr; | ||
} | ||
|
||
void insert(std::string); | ||
bool deletion(Trie*&, std::string); | ||
bool search(std::string); | ||
bool haveChildren(Trie const*); | ||
}; | ||
|
||
// Iterative function to insert a key in the Trie | ||
void Trie::insert(std::string key) | ||
{ | ||
// start from root node | ||
Trie* curr = this; | ||
for (int i = 0; i < key.length(); i++) | ||
{ | ||
// create a new node if path doesn't exists | ||
if (curr->character[key[i]] == nullptr) | ||
curr->character[key[i]] = new Trie(); | ||
|
||
// go to next node | ||
curr = curr->character[key[i]]; | ||
} | ||
|
||
// mark current node as leaf | ||
curr->isLeaf = true; | ||
} | ||
|
||
// Iterative function to search a key in Trie. It returns true | ||
// if the key is found in the Trie, else it returns false | ||
bool Trie::search(std::string key) | ||
{ | ||
// return false if Trie is empty | ||
if (this == nullptr) | ||
return false; | ||
|
||
Trie* curr = this; | ||
for (int i = 0; i < key.length(); i++) | ||
{ | ||
// go to next node | ||
curr = curr->character[key[i]]; | ||
|
||
// if string is invalid (reached end of path in Trie) | ||
if (curr == nullptr) | ||
return false; | ||
} | ||
|
||
// if current node is a leaf and we have reached the | ||
// end of the string, return true | ||
return curr->isLeaf; | ||
} | ||
|
||
// returns true if given node has any children | ||
bool Trie::haveChildren(Trie const* curr) | ||
{ | ||
for (int i = 0; i < CHAR_SIZE; i++) | ||
if (curr->character[i]) | ||
return true; // child found | ||
|
||
return false; | ||
} | ||
|
||
// Recursive function to delete a key in the Trie | ||
bool Trie::deletion(Trie*& curr, std::string key) | ||
{ | ||
// return if Trie is empty | ||
if (curr == nullptr) | ||
return false; | ||
|
||
// if we have not reached the end of the key | ||
if (key.length()) | ||
{ | ||
// recurse for the node corresponding to next character in the key | ||
// and if it returns true, delete current node (if it is non-leaf) | ||
|
||
if (curr != nullptr && | ||
curr->character[key[0]] != nullptr && | ||
deletion(curr->character[key[0]], key.substr(1)) && | ||
curr->isLeaf == false) | ||
{ | ||
if (!haveChildren(curr)) | ||
{ | ||
delete curr; | ||
curr = nullptr; | ||
return true; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
// if we have reached the end of the key | ||
if (key.length() == 0 && curr->isLeaf) | ||
{ | ||
// if current node is a leaf node and don't have any children | ||
if (!haveChildren(curr)) | ||
{ | ||
// delete current node | ||
delete curr; | ||
curr = nullptr; | ||
|
||
// delete non-leaf parent nodes | ||
return true; | ||
} | ||
|
||
// if current node is a leaf node and have children | ||
else | ||
{ | ||
// mark current node as non-leaf node (DON'T DELETE IT) | ||
curr->isLeaf = false; | ||
|
||
// don't delete its parent nodes | ||
return false; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
// C++ implementation of Trie Data Structure - Insertion, Searching and Deletion | ||
int main() | ||
{ | ||
Trie* head = new Trie(); | ||
|
||
head->insert("hello"); | ||
std::cout << head->search("hello") << " "; // print 1 | ||
|
||
head->insert("helloworld"); | ||
std::cout << head->search("helloworld") << " "; // print 1 | ||
|
||
std::cout << head->search("helll") << " "; // print 0 (Not found) | ||
|
||
head->insert("hell"); | ||
std::cout << head->search("hell") << " "; // print 1 | ||
|
||
head->insert("h"); | ||
std::cout << head->search("h"); // print 1 | ||
|
||
std::cout << std::endl; | ||
|
||
head->deletion(head, "hello"); | ||
std::cout << head->search("hello") << " "; // print 0 ("hello" deleted) | ||
std::cout << head->search("helloworld") << " "; // print 1 | ||
std::cout << head->search("hell"); // print 1 | ||
|
||
std::cout << std::endl; | ||
|
||
head->deletion(head, "h"); | ||
std::cout << head->search("h") << " "; // print 0 ("h" deleted) | ||
std::cout << head->search("hell") << " "; // print 1 | ||
std::cout << head->search("helloworld"); // print 1 | ||
|
||
std::cout << std::endl; | ||
|
||
head->deletion(head, "helloworld"); | ||
std::cout << head->search("helloworld") << " "; // print 0 ("helloworld" deleted) | ||
std::cout << head->search("hell") << " "; // print 1 | ||
|
||
head->deletion(head, "hell"); | ||
std::cout << head->search("hell"); // print 0 | ||
|
||
std::cout << std::endl; | ||
|
||
if (head == nullptr) | ||
std::cout << "Trie empty!!\n"; // Trie is empty now | ||
|
||
std::cout << head->search("hell"); // print 0 | ||
|
||
return 0; | ||
} |