From c56338df1470814fa24f39795d791ecb7c5028ff Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Fri, 22 Nov 2019 20:07:03 -0300
Subject: [PATCH] Add Cultivando Strings

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 contests/Cadernaveis/URI1141.cpp | 117 +++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)
 create mode 100644 contests/Cadernaveis/URI1141.cpp

diff --git a/contests/Cadernaveis/URI1141.cpp b/contests/Cadernaveis/URI1141.cpp
new file mode 100644
index 0000000..36bf967
--- /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;
+}
-- 
GitLab