Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <fstream>
- using namespace std;
- char NUL = 'a' - 1;
- int SIZE = 'z' - 'a' + 2;
- struct Item
- {
- int left;
- int right;
- Item *parent;
- Item **children;
- Item *suffix;
- int num;
- Item(int l = -1, int r = -1, Item *p = NULL)
- {
- left = l;
- right = r;
- parent = p;
- children = new Item* [SIZE];
- for (int i = 0; i < SIZE; i++)
- {
- children[i] = NULL;
- }
- }
- };
- struct Position
- {
- Item *vertex;
- int shift;
- Position(Item *v, int s)
- {
- vertex = v;
- shift = s;
- }
- };
- Item *last;
- Item *root = new Item(-1, -1, NULL);
- String s;
- void add(Position *position, int l, int r)
- {
- if (position->shift == 0)
- {
- position->vertex->children[s[i] - NUL] = new Item(l, r, position->vertex);
- last = position->vertex->children[s[l] - NUL];
- }
- else
- {
- Item *temp = new Item(position->vertex->left, position->vertex->right - position->shift, position->vertex->parent);
- position->vertex->left = position->vertex->right - position->shift + 1;
- position->vertex->parent = temp;
- temp->parent->children[s[temp->left] - NUL] = temp;
- temp->children[s[position->vertex->left] - NUL] = position->vertex;
- temp->children[s[l] - NUL] = new Item(l, r, temp);
- last = temp->children[s[l] - NUL];
- }
- }
- void jump(Position *pos, int pretailL, int pretailR)
- {
- while (pretailR - pretailL >= 0)
- {
- pos->vertex = pos->vertex->children[s[pretailL] - NUL];
- pos->shift = pos->vertex->right - pos->vertex->left + 1;
- if (pretailL + pos->shift <= pretailR + 1)
- {
- pretailL += pos->shift;
- pos->shift = 0;
- }
- else
- {
- pos->shift -= pretailR - pretailL + 1;
- pretailL = pretailR + 1;
- }
- }
- }
- int go(Position *pos, int tailL, int tailR)
- {
- while (tailR - tailL >= 0)
- {
- if (pos->shift == 0)
- {
- if (pos->vertex->children[s[tailL] - NUL] == NULL)
- {
- return tailL;
- }
- else
- {
- pos->vertex = pos->vertex->children[s[tailL] - NUL];
- pos->shift = pos->vertex->right - pos->vertex->left + 1;
- }
- }
- if (s[tailL] == s[pos->vertex->right - pos->shift + 1])
- {
- tailL++;
- pos->shift--;
- }
- else
- {
- return tailL;
- }
- }
- return tailL;
- }
- long long countSubstrings(Item *vertex)
- {
- long long res = 0;
- for (int i = 1; i < SIZE; i++)
- {
- if (vertex->children[i] != NULL)
- {
- res += countSubstrings(vertex->children[i]);
- res += vertex->children[i]->right - vertex->children[i]->left + 1;
- if (s[vertex->children[i]->right] == NUL)
- {
- res--;
- }
- }
- }
- return res;
- }
- void addSuf(int i)
- {
- if (last == NULL)
- {
- add(new Position(root, 0), i, s->length() - 1);
- }
- else
- {
- Item *father = last->parent;
- int tailL = last->left;
- int tailR = last->right;
- if (father == root)
- {
- tailL++;
- Position *pos = new Position(father, 0);
- tailL = go(pos, tailL, tailR);
- add(pos, tailL, tailR);
- }
- else
- {
- Item *ver = father->parent;
- int pretailL = father->left;
- int pretailR = father->right;
- Position *pos = new Position(ver->suffix, 0);
- if (ver == root)
- {
- pretailL++;
- }
- jump(pos, pretailL, pretailR);
- if (pos->shift == 0)
- {
- father->suffix = pos->vertex;
- }
- tailL = go(pos, tailL, tailR);
- add(pos, tailL, tailR);
- if (father->suffix == NULL)
- {
- father->suffix = last->parent;
- }
- }
- }
- }
- int main()
- {
- std::ifstream input("count.in");
- std::ofstream output("count.out");
- input >> s;
- roof->suffix = root;
- for (int i = 0; i < s.length(); i++)
- {
- addSuf(i);
- }
- output << countSubstrings(root);
- }
Add Comment
Please, Sign In to add comment