Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <iostream>
- #include <fstream>
- #include <vector>
- #include <string>
- #include <map>
- using namespace std;
- struct Node;
- int* last_symbol_index;
- Node* root;
- string line;
- int global_node_index = 0;
- struct Node
- {
- Node* suffix_link;
- Node* parent;
- int start;
- int* end;
- int node_index;
- map<char, Node*> children;
- Node(): suffix_link(NULL), parent(NULL), start(0), end(last_symbol_index), node_index(global_node_index++) {}
- Node(Node* parent_, int start_)
- : suffix_link(NULL), parent(parent_), start(start_), end(last_symbol_index), node_index(global_node_index++) {}
- ~Node() { if(end != last_symbol_index) delete end; }
- int size() { return *end - start; }
- };
- struct State
- {
- Node* closest_node;
- int offset;
- State(Node* closest_node_, int offset_): closest_node(closest_node_), offset(offset_) {}
- };
- bool try_move_by_edge(State& state, int start, int end)
- {
- while(start < end)
- {
- if(state.offset == state.closest_node->size()) //offset covers edge
- {
- if(state.closest_node->children.count(line[start]) == 0) //no edge with current_symbol
- return false;
- state.closest_node = state.closest_node->children[line[start]];
- state.offset = 0;
- }
- else
- {
- int edge_length = state.closest_node->size();
- if(line[state.closest_node->start + state.offset] != line[start]) //next symbol of edge != current_symbol
- return false;
- if(end - start < edge_length - state.offset) //current_symbol is of the edge
- {
- state.offset += end - start;
- return true;
- }
- start += edge_length - state.offset;
- state.offset = edge_length;
- }
- }
- return true;
- }
- Node* split_current_edge(State& state)
- {
- if(state.offset == state.closest_node->size())
- return state.closest_node;
- if(state.offset == 0)
- return state.closest_node->parent;
- Node* split_node = new Node(state.closest_node->parent, state.closest_node->start);
- split_node->end = new int(state.closest_node->start + state.offset);
- state.closest_node->parent->children[line[state.closest_node->start]] = split_node;
- split_node->children[line[state.closest_node->start + state.offset]] = state.closest_node;
- state.closest_node->parent = split_node;
- state.closest_node->start += state.offset;
- return split_node;
- }
- void move_by_suffix_link(State& state)
- {
- if(state.closest_node->suffix_link != NULL)
- {
- state.closest_node = state.closest_node->suffix_link;
- }
- else
- {
- Node* current = state.closest_node;
- state.closest_node = current->parent;
- move_by_suffix_link(state);
- state.offset = state.closest_node->size();
- try_move_by_edge(state, current->start + (current->parent == root), *current->end);
- state.closest_node = current->suffix_link = split_current_edge(state);
- }
- }
- void output(Node* n, ofstream& fo, Node* exception)
- {
- for(auto child = n->children.begin(); child != n->children.end(); ++child)
- {
- if(child->second == exception)
- continue;
- fo << n->node_index << "\t->\t" << child->second->node_index
- << " [label=\""
- << line.substr(child->second->start, *child->second->end - child->second->start)
- << "\"];\n";
- output(child->second, fo, exception);
- }
- }
- void exterial_output(Node* n, ofstream& fo, Node* exception)
- {
- fo << "digraph G {\n";
- output(n, fo, exception);
- fo << "}\n";
- }
- bool find_word(const string& word)
- {
- Node* search_node = root;
- for(auto word_symbol = word.begin(); word_symbol != word.end();)
- {
- if(search_node->children.count(*word_symbol) == 0)
- return false;
- search_node = search_node->children[*word_symbol];
- for
- (
- int edge_it = search_node->start;
- edge_it < *search_node->end && word_symbol != word.end();
- ++edge_it, ++word_symbol
- )
- if(line[edge_it] != *word_symbol)
- return false;
- }
- return true;
- }
- int main()
- {
- ifstream fi("input.txt");
- ofstream fo("output.txt");
- getline(fi, line);
- last_symbol_index = new int(line.size());
- root = new Node();
- root->end = new int(0);
- root->suffix_link = root;
- State start_point(root, 0);
- for(int current_symbol_index = 0; current_symbol_index < line.size(); ++current_symbol_index)
- {
- while(!try_move_by_edge(start_point, current_symbol_index, current_symbol_index + 1))
- {
- Node* middle_node = start_point.closest_node = split_current_edge(start_point);
- start_point.closest_node->children[line[current_symbol_index]] =
- new Node(start_point.closest_node, current_symbol_index);
- move_by_suffix_link(start_point);
- start_point.offset = start_point.closest_node->size();
- if(middle_node == root)
- break;
- }
- }
- /*
- ofstream graph_fo("output_graph.txt");
- exterial_output(root, graph_fo, NULL);
- graph_fo.close();
- */
- int number_of_words;
- fi >> number_of_words >> ws;
- for(int word_index = 0; word_index < number_of_words; ++word_index)
- {
- string word;
- getline(fi, word);
- fo << find_word(word) << " ";
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment