Advertisement
AlexG2230954

Untitled

Sep 24th, 2023 (edited)
817
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.05 KB | None | 0 0
  1. #include <iostream>
  2. #include <memory>
  3. #include <vector>
  4. #include <string>
  5. #include <set>
  6.  
  7. using namespace std;
  8.  
  9. struct TStringSlice {
  10.     const string& SourceString;
  11.     size_t Start;
  12.     shared_ptr<size_t> End;
  13.  
  14.     TStringSlice(const string& str, const size_t& start, shared_ptr<size_t> end)
  15.         : SourceString(str), Start(start), End(end) {}
  16.  
  17.     TStringSlice(const string& str, const size_t& start, size_t end)
  18.         : SourceString(str), Start(start), End(make_shared<size_t>(end)) {}
  19.  
  20.     char operator[](const size_t& i) const {
  21.         return SourceString[Start + i];
  22.     }
  23.  
  24.     void Update(const TStringSlice& other) {
  25.         Start = other.Start;
  26.         End = other.End;
  27.     }
  28.  
  29.     size_t Length() const {
  30.         return *End - this->Start;
  31.     }
  32.  
  33.     string ToString() const {
  34.         return SourceString.substr(Start, (*End) - Start);
  35.     }
  36.  
  37.     TStringSlice Slice(int a, int b) const {
  38.         size_t newStart = a == -1 ? Start : Start + a;
  39.         if (b == -1)
  40.             return TStringSlice(SourceString, newStart, End);
  41.         return TStringSlice(SourceString, newStart, Start + b);
  42.     }
  43.  
  44. };
  45.  
  46. struct TNode;
  47.  
  48. struct TEdge {
  49.     TStringSlice Value;
  50.     TNode* Node;
  51.  
  52.     void Split(size_t index);
  53.  
  54. };
  55.  
  56. struct TNode {
  57.     vector<TEdge> Children;
  58.     TNode* Parent = nullptr;
  59.     TNode* SuffixLink = nullptr;
  60.     size_t ParentEdge = 0;
  61.     int TextFlag = 0;
  62.  
  63.     TNode* Add(const TEdge& edge) {
  64.         Children.push_back(edge);
  65.  
  66.         TEdge* createdEdge = &(Children[Children.size() - 1]);
  67.         createdEdge->Node->Parent = this;
  68.         createdEdge->Node->ParentEdge = Children.size() - 1;
  69.  
  70.         return edge.Node;
  71.     }
  72.  
  73. };
  74.  
  75. void TEdge::Split(size_t index) {
  76.     TNode* newNode = new TNode();
  77.     newNode->Parent = Node->Parent;
  78.     newNode->ParentEdge = Node->ParentEdge;
  79.     Node->Parent = newNode;
  80.     newNode->Add({Value.Slice(index, -1), Node});
  81.     Node = newNode;
  82.     Value.Update(Value.Slice(-1, index));
  83. }
  84.  
  85. struct TCursor {
  86.     TNode* Node;
  87.     TEdge* Edge = nullptr;
  88.     size_t Index = 0;
  89.  
  90.     void MoveToNode(TNode* node) {
  91.         this->Node = node;
  92.         Edge = nullptr;
  93.         Index = 0;
  94.     }
  95.  
  96.     void ChooseEdgeByChar(char chr) {
  97.         for(TEdge& nodeEdge: Node->Children) {
  98.             if (nodeEdge.Value[0] == chr) {
  99.                 Edge = &nodeEdge;
  100.                 Index = 0;
  101.                 break;
  102.             }
  103.         }
  104.     }
  105.  
  106.     void MoveToParentEdge() {
  107.         Edge = &(Node->Parent->Children[Node->ParentEdge]);
  108.         Node = Node->Parent;
  109.         Index = Edge->Value.Length() - 1;
  110.     }
  111.  
  112.     bool Next(char chr) {
  113.         if (!IsNode() && (Index + 1 >= Edge->Value.Length()))
  114.             MoveToNode(Edge->Node);
  115.  
  116.         if (Edge == nullptr) {
  117.             ChooseEdgeByChar(chr);
  118.             return Edge != nullptr;
  119.         }
  120.  
  121.         if (Edge->Value[Index + 1] != chr)
  122.             return false;
  123.    
  124.         Index++;
  125.         return true;
  126.     }
  127.  
  128.     bool Prev() {
  129.         if (IsNode()) {
  130.             if (Node->Parent != nullptr) {
  131.                 MoveToParentEdge();
  132.                 return true;
  133.             }
  134.             return false;
  135.         }
  136.  
  137.         if (Index == 0) {
  138.             Edge = nullptr;
  139.             return true;
  140.         }
  141.  
  142.         Index--;
  143.         return true;
  144.     }
  145.  
  146.     bool IsNode() const {
  147.         return Edge == nullptr;
  148.     }
  149.  
  150. };
  151.  
  152. struct TCompactTrie {
  153.     TNode Root;
  154.  
  155.     TCursor GetCursor() {
  156.         return {&Root};
  157.     }
  158. };
  159.  
  160. struct TState {
  161.     const string& SourceString;
  162.     TCursor Cursor;
  163.     int TextFlag;
  164.     shared_ptr<size_t> End;
  165.     TNode* LastMiddleNode;
  166.     bool NeedUpdate;
  167. };
  168.  
  169. void InsertString(const TStringSlice& str, TState& state);
  170. void Iterate(const TStringSlice& str, bool fastMode, TState& state);
  171. void GoBack(TState& state);
  172.  
  173. void UpdateSuffixLinks(TState& state) {
  174.     if (state.LastMiddleNode != nullptr) {
  175.         state.LastMiddleNode->SuffixLink = state.Cursor.Node;
  176.     }
  177.     state.LastMiddleNode = state.Cursor.Node;
  178. }
  179.  
  180. void UpdateTextFlag(TState& state) {
  181.     set<TNode*> seenNodes;
  182.  
  183.     while (!state.Cursor.IsNode()) {
  184.         state.Cursor.MoveToNode(state.Cursor.Edge->Node);
  185.        
  186.         if(seenNodes.find(state.Cursor.Node) == seenNodes.end()) {
  187.             state.Cursor.Node->TextFlag |= state.TextFlag;
  188.             seenNodes.insert(state.Cursor.Node);
  189.             GoBack(state);
  190.         }
  191.     }
  192. }
  193.  
  194. void InsertString(const TStringSlice& str, TState& state) {
  195.  
  196.     if (state.Cursor.IsNode()) {
  197.         TNode* newNode = state.Cursor.Node->Add({str, new TNode()});
  198.         newNode->TextFlag |= state.TextFlag;
  199.         state.NeedUpdate = state.Cursor.Node->Parent != nullptr;
  200.         state.Cursor.MoveToNode(newNode);
  201.     } else {
  202.         state.Cursor.Edge->Split(state.Cursor.Index + 1);
  203.         state.Cursor.MoveToNode(state.Cursor.Edge->Node);
  204.         UpdateSuffixLinks(state);
  205.         TNode* newNode = state.Cursor.Node->Add({str, new TNode()});
  206.         newNode->TextFlag |= state.TextFlag;
  207.         state.Cursor.MoveToNode(newNode);
  208.         state.NeedUpdate = true;
  209.     }
  210.  
  211. }
  212.  
  213. void Iterate(const TStringSlice& str, bool fastMode, TState& state) {
  214.  
  215.     size_t index = 0;
  216.  
  217.     while (index < str.Length()) {
  218.         if (!state.Cursor.Next(str[index])) {
  219.  
  220.             InsertString(str.Slice(index, -1), state);
  221.             break;
  222.         }
  223.  
  224.         if (fastMode) {
  225.             size_t minLength = min(
  226.                 state.Cursor.Edge->Value.Length(),
  227.                 str.Length() - index
  228.             ) - 1;
  229.  
  230.             state.Cursor.Index = minLength;
  231.             index += minLength;
  232.         }
  233.  
  234.         index++;
  235.        
  236.     }
  237. }
  238.  
  239. TEdge* JumpToParent(TCursor& cursor) {
  240.     cursor.Prev();
  241.     TEdge* parentEdge = cursor.Edge;
  242.     cursor.MoveToNode(cursor.Node);
  243.     return parentEdge;
  244. }
  245.  
  246. void GoBack(TState& state) {
  247.    
  248.     TEdge* edge = JumpToParent(state.Cursor);
  249.  
  250.     if (state.Cursor.Node->Parent != nullptr) {
  251.         if (state.Cursor.Node->SuffixLink != nullptr) {
  252.             state.Cursor.MoveToNode(state.Cursor.Node->SuffixLink);
  253.         } else {
  254.             GoBack(state);
  255.         }
  256.  
  257.         Iterate(edge->Value, !edge->Node->Children.empty(), state);
  258.     } else {
  259.         Iterate(edge->Value.Slice(1, -1), !edge->Node->Children.empty(), state);
  260.     }
  261. }
  262.  
  263. void StartStep(TState& state) {
  264.  
  265.     state.NeedUpdate = true;
  266.  
  267.     while(state.NeedUpdate) {
  268.         state.NeedUpdate = false;
  269.        
  270.         if (state.Cursor.IsNode()) {
  271.             GoBack(state);
  272.         } else {
  273.             Iterate({state.SourceString, (*state.End) - 1, state.End}, false, state);
  274.         }
  275.     }
  276. }
  277.  
  278. TCompactTrie* BuildSuffixTrie(const string& str, TCompactTrie* trie = nullptr, int textFlag = 0) {
  279.     TCompactTrie* t = (trie == nullptr) ? new TCompactTrie() : trie;
  280.     TState state { str, t->GetCursor(), textFlag, make_shared<size_t>(0), nullptr, false };
  281.  
  282.     (*state.End)++;
  283.     Iterate({str, 0, state.End}, false, state);
  284.  
  285.     while((*state.End) < str.size()) {
  286.         (*state.End)++;
  287.         StartStep(state);
  288.         state.LastMiddleNode = nullptr;
  289.        
  290.     }
  291.  
  292.     UpdateTextFlag(state);
  293.     return t;
  294. }
  295.  
  296. void ExtendTextFlags(TNode* node) {
  297.     for (const TEdge& child: node->Children) {
  298.         ExtendTextFlags(child.Node);
  299.         node->TextFlag |= child.Node->TextFlag;
  300.     }
  301. }
  302.  
  303. TCompactTrie* BuildCommonSuffixTree(string& s1, string& s2) {
  304.     TCompactTrie* trie = BuildSuffixTrie(s1, nullptr, 1);
  305.     BuildSuffixTrie(s2, trie, 2);
  306.     ExtendTextFlags(&(trie->Root));
  307.     return trie;
  308. }
  309.  
  310. size_t CalculateMaxCommonSubstringSize(const TNode& node) {
  311.     if(node.Children.empty()) return -1;
  312.     size_t maximalSize = 0;
  313.  
  314.     for(const TEdge& child : node.Children) {
  315.         if(child.Node->TextFlag == 3) {
  316.             maximalSize = max(
  317.                 maximalSize,
  318.                 child.Value.Length() + CalculateMaxCommonSubstringSize(*(child.Node))
  319.             );
  320.         }
  321.     }
  322.     return maximalSize;
  323. }
  324.  
  325. void RestoreString(const TNode* node, string& outString) {
  326.     while(node->Parent != nullptr) {
  327.         const TEdge& x = node->Parent->Children[node->ParentEdge];
  328.         outString.insert(0, x.Value.ToString());
  329.         node = node->Parent;
  330.     };
  331. }
  332.  
  333. void FindCommonSubstringsBySpecifiedSize(
  334.     const TNode& node,
  335.     const size_t& maximalSize,
  336.     const size_t& currentSize,
  337.     set<string> & substrings
  338. ) {
  339.     if(currentSize == maximalSize) {
  340.         string foundSubstring;
  341.         RestoreString(&node, foundSubstring);
  342.         if (foundSubstring.back() == '$')
  343.             foundSubstring.pop_back();
  344.         substrings.insert(foundSubstring);
  345.         return;
  346.     }
  347.  
  348.     if(currentSize > maximalSize) {
  349.         return;
  350.     }
  351.  
  352.     for(const TEdge& child : node.Children) {
  353.         if(child.Node->TextFlag == 3) {
  354.             size_t nextLength = child.Value.Length();
  355.  
  356.             if(child.Node->Children.empty())
  357.                 nextLength--;
  358.  
  359.             FindCommonSubstringsBySpecifiedSize(
  360.                 *(child.Node),
  361.                 maximalSize,
  362.                 currentSize + nextLength,
  363.                 substrings
  364.             );
  365.         }
  366.     }
  367. }
  368.  
  369. void FindCommonSubstrings(TCompactTrie& trie, set<string> & results) {
  370.     size_t maxLength = CalculateMaxCommonSubstringSize(trie.Root);
  371.     FindCommonSubstringsBySpecifiedSize(
  372.         trie.Root,
  373.         maxLength,
  374.         0,
  375.         results
  376.     );
  377. }
  378.  
  379. const char SENTINEL = '$';
  380.  
  381. int main() {
  382.     ios_base::sync_with_stdio(false);
  383.     cin.tie(nullptr);
  384.  
  385.     string a, b;
  386.     set<string> results;
  387.     getline(cin, a);
  388.     getline(cin, b);
  389.  
  390.     a += SENTINEL;
  391.     b += SENTINEL;
  392.  
  393.     TCompactTrie* trie = BuildCommonSuffixTree(a, b);
  394.  
  395.     FindCommonSubstrings(*trie, results);
  396.  
  397.     bool sizePrinted = false;
  398.  
  399.     for(const string& result: results) {
  400.         if(result.size() == 0) {
  401.             break;
  402.         }
  403.  
  404.         if(!sizePrinted) {
  405.             cout << result.size();
  406.             sizePrinted = true;
  407.         }
  408.  
  409.         cout << "\n" << result;
  410.     }
  411.  
  412.     return 0;
  413. }
  414.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement