-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path2003 S4 - Substrings.cpp
72 lines (46 loc) · 2.09 KB
/
2003 S4 - Substrings.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
2003 S4 - Substrings
Difficulty: Medium
For this problem, you just need to know either suffix tree or suffix array, either work.
If you don't know about these structures, then that's probably why you can't solve this problem.
A good channel to check out to learn about suffix arrays is WilliamFiset, he even has a video that solves this problem
Basically we just have a suffix array, which is all the suffixes of string S, sorted
Afterwards, we count what is the length of the longest prefix between two adjacent suffixes, this tells us how many duplicates there are
We total all these duplicates.
Afterwards, we recognize that excluding the "" substring, there are n(n + 1) / 2 substrings for a string with length n
You could derive this from the arithmetic series formula with n(a1 + a2) / 2
n would be the length of our string and so would a1.
a2 would be the minimum substring length which is 1.
This gives us the formula.
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
int main(){
int N; std::cin >> N;
for (int n = 0; n < N; n++){
std::string S;
std::cin >> S;
std::vector<std::string> suffix; //Suffix array, holds all the suffixes
//Get all suffixes
for (int i = 0; i < S.length(); i++){
suffix.push_back(S.substr(i, S.length() - i));
}
std::sort(suffix.begin(), suffix.end()); //Sort lexicographically
int lcp = 0; //Longest common prefix total
//For each suffix, compare with previous one
for (int i = 1; i < suffix.size(); i++){
int index = 0; //Char index in suffixes
while (true){
//If they don't match, break
if (suffix[i][index] != suffix[i - 1][index]) break;
lcp++; index++; //Otherwise, add it to the lcp
}
}
//Our answer, 1 for the "" substring and then we use our formula for total substrings - lcp which represents the duplicates
int count = 1 + ((S.length() * (S.length() + 1)) / 2) - lcp;
std::cout << count << '\n';
}
return 0;
}