diff --git a/contests/Cadernaveis/URI1141.cpp b/contests/Cadernaveis/URI1141.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36bf967bdb17e9a9fb6473d4a81f3f7fe5d357df --- /dev/null +++ b/contests/Cadernaveis/URI1141.cpp @@ -0,0 +1,117 @@ +/// Cultivando Strings + +#include <bits/stdc++.h> + +#define EPS 1e-6 +#define MOD 1000000007 +#define inf 0x3f3f3f3f +#define llinf 0x3f3f3f3f3f3f3f3f + +#define fi first +#define se second +#define pb push_back +#define ende '\n' + +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +#define mset(x, y) memset(&x, (y), sizeof(x)) + +using namespace std; + +using ll = long long; +using ii = pair<int,int>; + +struct AhoCorasick { + struct Node { + int fail; + vector<int> words; + map<char,int> next; + + Node() : fail(0) {} + int has(char i) { return next.count(i); } + int &operator[](char i) { return next[i]; } + }; + + vector<Node> trie; + + AhoCorasick(const vector<string> &v) { + trie.pb(Node()); + build(v); + preprocess(); + } + + int insert(const string &s) { + int n = 0; + for (int i = 0; i < s.size(); n = trie[n][s[i]], ++i) + if (!trie[n].has(s[i])) { + trie[n][s[i]] = trie.size(); + trie.pb(Node()); + } + return n; + } + + void build(const vector<string> &v) { + for (int i = 0; i < v.size(); ++i) { + int n = insert(v[i]); + trie[n].words.pb(i); + } + } + + inline int suffix(int v, char c) { + while (v != 0 && !trie[v].has(c)) v = trie[v].fail; + if (trie[v].has(c)) v = trie[v][c]; + return v; + } + + void preprocess() { + vector<int> Q = { 0 }; + for (int i = 0; i != Q.size(); ++i) { + int u = Q[i]; + for (auto j : trie[u].next) { + trie[j.se].fail = u ? suffix(trie[u].fail, j.fi) : trie[u].fail; + trie[j.se].words.insert(trie[j.se].words.end(), all(trie[trie[j.se].fail].words)); + Q.pb(j.se); + } + } + } +}; + +int n; +int dp[10101]; +vector<string> v; + +int solve(int i, AhoCorasick &aho) { + if (i == n) return 0; + if (dp[i] != -1) return dp[i]; + + int u = 0; + int grt = 0; + for (auto j : v[i]) { + u = aho.suffix(u, j); + for (auto k : aho.trie[u].words) + if (v[k].size() < v[i].size()) + grt = max(grt, solve(k, aho) + 1); + } + + return dp[i] = grt; +} + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + while (cin >> n && n) { + v.clear(); + v.resize(n); + for (auto &i : v) cin >> i; + AhoCorasick aho(v); + + mset(dp, -1); + int ans = 0; + for (int i = 0; i < n; ++i) + ans = max(ans, solve(i, aho) + 1); + cout << ans << ende; + } + + return 0; +}