#include #include #include #include bool CmpStrEx(const std::string& expr, const std::string& str) { if(expr.empty() || str.empty()) return false; struct State { struct Block { const size_t b,len; const bool optional; Block(const size_t bb,const size_t ee,const bool o):b(bb),len(ee-bb),optional(o) {} }; struct Cursor { size_t block,offset; bool operator <(const struct Cursor& c) const { if(blockc.block) return false; if(offset Cursors; typedef std::set::iterator pCursor; std::vector blockchain; Cursors cursors; const std::string& s; Cursors InitCursors(size_t block) const { Cursors cs; for(size_t i=block; ibpos) blockchain.push_back(Block(bpos,cur,(']'==s[cur]))); cur++; bpos=cur; continue; } cur++; } // Add last block if(bposblock]; if(c==s[bl.b+p->offset]) {res=true; ++p;} else p=cursors.erase(p); } // Increment cursors Cursors upd; // New cursors p=cursors.begin(); while(p!=cursors.end()) { // Increment cursor on one position if(p->offset+1>=blockchain[p->block].len) // Go to next block { Cursors cs=InitCursors(p->block+1); // Get cursors for next block p=cursors.erase(p); // Erase current cursor for(const auto& cur: cs) upd.insert(cur); // Copy cursors to new set continue; } else upd.insert({p->block,p->offset+1}); if(blockchain[p->block].optional) // If current block is optional next symbol may be from next block { Cursors cs=InitCursors(p->block+1); // Get cursors for next blockchain for(const auto& cur: cs) upd.insert(cur); // Copy cursors to new set } ++p; } cursors=upd; return res; } }; struct State st(expr); for(size_t pos=0; pos