Pagini recente » Cod sursa (job #3325518) | Cod sursa (job #247703) | Cod sursa (job #3128490) | Cod sursa (job #711330) | Cod sursa (job #3351206)
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <limits.h>
#include <chrono>
#include <numeric>
#include <iomanip>
#include <vector>
#include <string>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <bitset>
#include <deque>
#include <stack>
#include <queue>
#include <list>
#include <string.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef vector<pll> vll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<bool> vb;
typedef vector<vb> vvb;
template <class T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
double EPS = 1e-9;
int INF = 1000000005;
long long INFF = 1000000000000000005LL;
double PI = acos(-1);
#define M 1000000007
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
// auto lim=unique(all(v));
// v.resize(distance(v.begin(), lim));
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
struct pair_custom_hash {
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& p) const
{
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
auto hash1 = splitmix64(p.first+FIXED_RANDOM);
auto hash2 = splitmix64(p.second+FIXED_RANDOM);
return hash1^hash2;
}
};
ll gcd(ll a,ll b){
ll r;
while(b){
r=a%b;
a=b;
b=r;
}
return a;
}
ll lcm(ll a,ll b){
return a*b/gcd(a,b);
}
template<class T> T nxt() {
T x;
cin >> x;
return x;
}
class TrieNode{
public:
TrieNode* children[26];
int noWords;
TrieNode(){
noWords=0;
memset( children, 0, sizeof( children ) );
}
};
void insertWord(TrieNode* root,const string& word){
TrieNode* currentNode=root;
for(auto character:word){
int position=character-'a';
if(currentNode->children[position]==nullptr){
// Create a new node
currentNode->children[position]=new TrieNode();
}
currentNode=(currentNode->children[position]);
}
currentNode->noWords++;
}
int getCountOfWord(TrieNode* root,const string& word){
TrieNode* currentNode=root;
for(char character:word){
int position=character-'a';
// If no node in the direction of this word,it doesn't exists and its count is 0
if(currentNode->children[position]==nullptr){
return 0;
}
currentNode=currentNode->children[position];
}
return currentNode->noWords;
}
int getLongestCommonPrefixLength(TrieNode* root,const string& word){
TrieNode* currentNode=root;
int n=word.size();
for(int i=0;i<n;++i){
int position=word[i]-'a';
if(currentNode->children[position]==nullptr){
return i;
}
currentNode=currentNode->children[position];
}
return word.size();
}
int countChildren(TrieNode* node){
// Count number of children of node that are not null
int count=26;
for(int i=0;i<26;++i){
count-=(node->children[i]==nullptr);
}
return count;
}
void deleteWord(TrieNode* root,const string& word){
TrieNode* currentNode=root;
if(!getCountOfWord(root,word)){
return;
}
int n=word.size();
int startPos=0;
stack<TrieNode*> path;
path.push(currentNode);
for(int i=0;i<n;++i){
int position=word[i]-'a';
currentNode=currentNode->children[position];
if(i<n-1&&(currentNode->noWords||countChildren(currentNode)>1)){
startPos=i+1;
}
path.push(currentNode);
}
currentNode->noWords--;
if(!currentNode->noWords&&!countChildren(currentNode)){
for(int i=n-1;i>=startPos;--i){
// Delete an empty node
delete path.top();
path.pop();
TrieNode* node=path.top();
int position=word[i]-'a';
node->children[position]=nullptr;
}
}
}
bool deleteWordRec(TrieNode* root,TrieNode* node,const string& word,int k){
if(k==int(word.size())){
node->noWords--;
}
else{
int position=word[k]-'a';
bool deletedChildren=deleteWordRec(root,node->children[position],word,k+1);
if(deletedChildren){
node->children[position]=nullptr;
}
}
if(!node->noWords&&!countChildren(node)&&node!=root){
delete node;
return 1;
}
return 0;
}
void SolveConsole(){
int n;
cin>>n;
TrieNode* root=new TrieNode();
for(int i=0;i<n;++i){
int t;
string w;
cin>>t>>w;
if(t==0){
insertWord(root,w);
}
else if(t==1){
deleteWordRec(root,root,w,0);
}
else if(t==2){
cout<<getCountOfWord(root,w)<<'\n';
}
else if(t==3){
cout<<getLongestCommonPrefixLength(root,w)<<'\n';
}
else{
exit(1);
}
}
}
void SolveFile(string fileName){
int n;
cin>>n;
TrieNode* root=new TrieNode();
std::ifstream instream(fileName+".in");
string lineText;
while(getline(instream,lineText)){
int t=lineText[0]-'0';
string w=lineText.substr(2,30);
if(t==0){
insertWord(root,w);
}
else if(t==1){
deleteWord(root,w);
// deleteWord2(root,w);
}
else if(t==2){
cout<<getCountOfWord(root,w)<<'\n';
}
else if(t==3){
cout<<getLongestCommonPrefixLength(root,w)<<'\n';
}
else{
exit(1);
}
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
freopen("trie.in", "r", stdin);
freopen("trie.out", "w", stdout);
SolveFile("trie");
// SolveConsole();
return 0;
}