Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <set>
- #include <fstream>
- #include <queue>
- #include <stack>
- #include <string>
- #include <time.h>
- #include <limits>
- using namespace std;
- //Cтруктура ситуации
- struct situation {
- string leftPart, RightPart;
- int position, index;
- situation() {
- position = 0;
- index = 0;
- RightPart = "";
- }
- situation(string left, string right, int pos, int ix) {
- leftPart = left;
- RightPart = right;
- position = pos;
- index = ix;
- }
- bool operator<(const situation s2) const {
- if (leftPart != s2.leftPart){
- return (leftPart < s2.leftPart);
- }
- if (RightPart != s2.RightPart){
- return (RightPart < s2.RightPart);
- }
- if (position != s2.position) {
- return position < s2.position;
- }
- if (index != s2.index) {
- return index < s2.index;
- }
- return false;
- }
- };
- //Расширенные ситуации
- struct wide_situation {
- string leftPart, RightPart;
- int position, index, indexOfD;
- wide_situation() : position(0), index(0), RightPart("") {
- }
- wide_situation(string left, string right, int pos, int ix, int indexOfDTmp) {
- leftPart = left;
- RightPart = right;
- position = pos;
- index = ix;
- indexOfD = indexOfDTmp;
- }
- };
- //проекция расширенной ситуации
- struct pi_situation {
- string leftPart, RightPart;
- int position;
- pi_situation() {
- position = 0;
- RightPart = "";
- }
- pi_situation(string l, string r, int p) {
- leftPart = l;
- RightPart = r;
- position = p;
- }
- pi_situation(wide_situation w) {
- pi_situation(w.leftPart, w.RightPart, w.position);
- }
- bool operator<(const pi_situation s2) const {
- if (leftPart != s2.leftPart){
- return (leftPart < s2.leftPart);
- }
- if (RightPart != s2.RightPart){
- return (RightPart < s2.RightPart);
- }
- if (position != s2.position) {
- return position < s2.position;
- }
- return false;
- }
- };
- class node {
- public:
- std::stack<pi_situation> stack;
- node() : q1(false), alreadyRead(0) {
- while (!stack.empty()) {
- stack.pop();
- }
- }
- int alreadyRead;
- bool q1;
- void write() {
- cout << "Already read = " << alreadyRead << endl;
- std::stack<pi_situation> stackTmp;
- while (!stack.empty()) {
- pi_situation s = stack.top();
- stack.pop();
- stackTmp.push(s);
- s.write();
- }
- cout << endl;
- while (!stackTmp.empty()) {
- stack.push(stackTmp.top());
- stackTmp.pop();
- }
- }
- };
- vector<situation> state[100000000]; //состояния
- vector<pair<string, string> > rules; //список правил
- set<situation> stateSet[100000000]; //множество состояний
- vector<wide_situation> wide_situations; //расширенные состояния
- vector<pi_situation> pi_situations; //проекции расширенных состояний
- set<pi_situation> pi_situationsSet; //множество расширенных состояний
- queue<node> q;
- string word;
- void countMoving(node nodeTMP) {
- //(q, a, (A -> x*aB)) -> (q, (A -> xa*B))
- node newNode;
- newNode = nodeTMP;
- if (newNode.alreadyRead < word.length()) {
- if (newNode.stack.size() > 0) {
- pi_situation current = newNode.stack.top();
- if (current.position == 2) {
- current.position = 2;
- }
- if (current.RightPart.length() > current.position && current.RightPart[current.position] == word[newNode.alreadyRead]) {
- ++newNode.alreadyRead;
- ++current.position;
- newNode.stack.pop();
- newNode.stack.push(current);
- q.push(newNode);
- }
- }
- }
- newNode = nodeTMP;
- //(q0, ε,(A → α · Bη)) → (q0,(A → α · Bβ)(B → ·β)) ∀ (B → β) ∈ P// я бы поставил n вместо b
- for (int i = 0; i < rules.size(); ++i) {
- if (nodeTMP.stack.size() > 0) {
- pi_situation current = nodeTMP.stack.top();
- if (current.RightPart.length() > current.position && current.RightPart[current.position] == rules[i].first[0] && rules[i].first.length() == 1) {
- newNode = nodeTMP;
- newNode.stack.pop();
- pi_situation newsituation = current;
- newsituation.leftPart = current.leftPart;
- // newsituation.RightPart = current.RightPart.erase((unsigned long) (current.pos + 1));
- //newsituation.RightPart += rules[i].second;
- newsituation.RightPart = current.RightPart;
- newNode.stack.push(newsituation);
- newsituation = current;
- newsituation.leftPart = rules[i].first;
- newsituation.RightPart = rules[i].second;
- newsituation.position = 0;
- newNode.stack.push(newsituation);
- q.push(newNode);
- }
- }
- }
- //(q0, ε,(A → α · Bη)(B → β·)) → (q0,(A → αB · η))
- newNode = nodeTMP;
- if (newNode.stack.size() > 1) {
- pi_situation currentSecond = newNode.stack.top();
- newNode.stack.pop();
- if (currentSecond.position == currentSecond.RightPart.size()) {
- pi_situation currentFirst = newNode.stack.top();
- newNode.stack.pop();
- if (currentFirst.RightPart.size() > currentFirst.position &&
- currentFirst.RightPart[currentFirst.position] == currentSecond.leftPart[0] && currentSecond.leftPart.length() == 1) {
- ++currentFirst.position;
- newNode.stack.push(currentFirst);
- q.push(newNode);
- }
- }
- }
- //hq0, ε,(S0 → S·)i → hq1, εi
- newNode = nodeTMP;
- if (newNode.stack.size() > 0) {
- pi_situation current = newNode.stack.top();
- newNode.stack.pop();
- if (current.leftPart == "$" && current.RightPart.size() == current.position) {
- newNode.q1 = true;
- q.push(newNode);
- }
- }
- }
- void countpi_situation() {
- for (int i = 0; i < wide_situations.size(); ++i) {
- pi_situations.push_back(pi_situation(wide_situations[i]));
- pi_situationsSet.insert(pi_situation(wide_situations[i]));
- }
- }
- void countwide_situations() {
- for (int i = 0; i < state->size(); ++i) {
- for (int j = 0; j < state[i].size(); ++j) {
- wide_situations.push_back(wide_situation(state[i][j].leftPart, state[i][j].RightPart, state[i][j].position,
- state[i][j].index, i));
- }
- }
- }
- void Scan(int j, char c) {
- for (int i = 0; i < state[j].size(); i++) {
- situation cur = state[j][i];
- if (cur.position < cur.RightPart.size() && cur.RightPart[cur.position] == c) {
- cur.position++;
- state[j + 1].push_back(cur);
- }
- }
- }
- void Predict(int j) {
- for (int i = 0; i < state[j].size(); i++) {
- situation cur = state[j][i];
- string R = getNonTerminal(cur.RightPart, cur.position);
- if (R.size() == 0)
- continue;
- for (int k = 0; k < rules.size(); k++) {
- situation rule = situation(rules[k].first, rules[k].second, 0, j);
- if (rules[k].first == R && stateSet[j].count(rule) == 0) {
- stateSet[j].insert(rule);
- state[j].push_back(situation(R, rules[k].second, 0, j));
- }
- }
- }
- }
- void Complete(int j) {
- for (int i = 0; i < state[j].size(); i++) {
- situation cur = state[j][i];
- if (cur.position != cur.RightPart.size())
- continue;
- int k = cur.index;
- for (int t = 0; t < state[k].size(); t++) {
- situation pred = state[k][t];
- string R = getNonTerminal(pred.RightPart, pred.position);
- if (R != cur.leftPart)
- continue;
- situation rule = situation(pred.leftPart, pred.RightPart, (int)(pred.position + R.size()), pred.index);
- if (stateSet[j].count(rule) == 0) {
- stateSet[j].insert(rule);
- situation put = pred;
- put.position += R.size();
- state[j].push_back(put);
- }
- }
- }
- }
- string getNonTerminal(string s, int pos) {
- string res = "";
- if (pos < s.size() && s[pos] <= 'Z' && s[pos] >= 'A')
- res += s[pos++];
- while (pos < s.size() && s[pos] >= '0' && s[pos] <= '9')
- res += s[pos++];
- return res;
- }
- int main() {
- ifstream grammar;
- grammar.open("grammar.txt");
- int n;
- grammar >> n;
- string S;
- for (int i = 0; i < n; i++) {
- string left;
- string right;
- grammar >> left;
- getline(grammar, right);
- for (int j = 0; j < right.size(); j++)
- if (right[j] == ' ') {
- right.erase(j, 1);
- j--;
- }
- if (i == 0)
- S = left;
- rules.push_back(make_pair(left, right));
- }
- rules.push_back(make_pair("$", S));
- state[0].push_back(situation("$", S, 0, 0));
- stateSet[0].insert(situation("$", S, 0, 0));
- grammar.close();
- getline(cin, word); //введем наше слово
- Predict(0);
- Complete(0);
- for (int i = 0; i < word.size(); i++) {
- Scan(i, word[i]);
- int oldSize = state[i].size();
- Predict(i + 1);
- Complete(i + 1);
- while (oldSize != state[i].size()) {
- oldSize = state[i].size();
- Predict(i + 1);
- Complete(i + 1);
- }
- }
- node init = node();
- //(q, e, e) -> (q, (S' -> S)
- init.stack.push(pi_situation("$", S, 0));
- bool answer = false;
- q.push(init);
- time_t timer = time(NULL);
- while (!q.empty()) {
- //отсечение по времени
- if (timer - time(NULL) > CLOCKS_PER_SEC * 10) {
- cout << "NO";
- return 1;
- }
- node tmp = q.front();
- if (tmp.alreadyRead == 1) {
- tmp.alreadyRead = 1;
- }
- //tmp.write(); красивый вывод ситуаций со стека
- q.pop();
- if (tmp.q1 && tmp.stack.empty() && tmp.alreadyRead == word.length()) {
- answer = true;
- break;
- }
- countMoving(tmp);
- }
- if (stateSet[word.size()].count(situation("$", S, 1, 0)) > 0) {
- cout << "YES" << endl;
- }
- else {
- cout << "NO" << endl;
- }
- if ((stateSet[word.size()].count(situation("$", S, 1, 0)) > 0) == answer) {
- cout << "answerCorrect";
- }
- else {
- cout << "fail";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement