mr_dot_convict

CF25E-Test-SPOJ-mr.convict

Jul 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.44 KB | None | 0 0
  1. // Hack it and have it ;) //
  2. /*author* Priyanshu Shrivastav (from IIT Palakkad) *
  3.  * *_ __ ___  _ ______ ___  _ ____   ___  ___| |_  *
  4.  * | '_ ` _ \| '__/ __/ _ \| '_ \ \ / / |/ __| __| *
  5.  * | | | | | | | | (_| (_) | | | \ V /| | (__| |_  *
  6.  * |_| |_| |_|_|(_)___\___/|_| |_|\_/ |_|\___|\__| *
  7. When I wrote this, only God and I understood what I was doing
  8.  ** * * * * * * * Now, only God knows * * * * * * */
  9. #include      <bits/stdc++.h>
  10. #include      <ext/pb_ds/assoc_container.hpp>
  11. #include      <ext/pb_ds/tree_policy.hpp>
  12. using namespace std;
  13. using namespace __gnu_pbds;
  14. #pragma GCC   optimize ("Ofast")
  15. #pragma GCC   optimize ("unroll-loops")
  16. #pragma GCC   target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
  17.  
  18. #define IOS   ios_base::sync_with_stdio(false); cin.tie (nullptr)
  19. #define PREC  cout.precision (10); cout << fixed
  20. #define x     first
  21. #define y     second
  22. #define bg(x) " [ " << #x << " : " << (x) << " ] "
  23. #define un(x) sort(x.begin(), x.end()), \
  24.               x.erase(unique(x.begin(), x.end()), x.end())
  25. using   ll  = long long;
  26. using   ull = unsigned long long;
  27. using   ff  = long double;
  28. using   pii = pair<int,int>;
  29. using   pil = pair<int,ll>;
  30. typedef tree
  31. < int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
  32. ordered_set;
  33.  
  34. struct chash {
  35.    int operator()(pii x) const { return x.x*31 + x.y; }
  36. };
  37. gp_hash_table <pii, int, chash> mp;
  38.  
  39. seed_seq seq{
  40.    (uint64_t) chrono::duration_cast<chrono::nanoseconds>
  41.       (chrono::high_resolution_clock::now().time_since_epoch()).count(),
  42.       (uint64_t) __builtin_ia32_rdtsc(),
  43.       (uint64_t) (uintptr_t) make_unique<char>().get()
  44. };
  45. mt19937 rng(seq); //uniform_int_distribution<int> (l, h)(rng); //[low, high]
  46.  
  47. #define debug(args...) { \
  48.    /* WARNING : do NOT compile this debug func calls with following flags: // \
  49.     * // -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2*/ \
  50.    string _s = #args; replace(_s.begin(), _s.end(), ',', ' ');\
  51.    stringstream _ss(_s); \
  52.    istream_iterator<string> _it(_ss); err(_it, args); \
  53. }
  54. void err(istream_iterator<string> it) {
  55.    it->empty(); cerr << " (Line : " << __LINE__ << ")" << '\n';
  56. }
  57. template<typename T, typename... Args>
  58. void err(istream_iterator<string> it, T a, Args... args) {
  59.    cerr << fixed << setprecision(15)
  60.       << " [ " <<  *it << " : " << a  << " ] "<< ' ';
  61.    err(++it, args...);
  62. }
  63. /*****************************************************************************/
  64.  
  65. struct polyhash {
  66.    static const int Mod = (int)1e9 + 123;
  67.    static vector <int> pow_int;
  68.    static int p; // take p such that a[i] < p < Mod, gcd(p, Mod) = 1
  69.    static int gen_base (const int l, const int r) {
  70.       int base = uniform_int_distribution<int>(l + 1, r) (rng);
  71.       return base % 2 == 0 ? base - 1 : base;
  72.    }
  73.    static void calc_pow(int mx_len) {
  74.       while ((int)pow_int.size() <= mx_len + 1) { // calc powers
  75.          pow_int.push_back(int(1ll * pow_int.back() * p % Mod));
  76.       }
  77.    }
  78.    const int sz;
  79.  
  80.    vector <int> s;
  81.    vector <int> pref_int;
  82.  
  83.    void encode(const string &st) {
  84.       s.assign(sz, 0);
  85.       for (int i = 0; i < sz; ++i) s[i] = st[i];
  86.    }
  87.  
  88.    polyhash (const string &st) : sz((int)st.size())
  89.    {
  90.       encode(st);
  91.       pref_int.assign(sz + 1u, 0);
  92.       assert(p < Mod);
  93.  
  94.       calc_pow(sz + 1);
  95.  
  96.       for (int i = 0; i < sz; ++i) {
  97.          assert(p > s[i]);
  98.          pref_int[i] = int(1ll*s[i]*pow_int[i] % Mod);
  99.          pref_int[i] = (pref_int[i] + (i > 0 ? pref_int[i - 1] : 0)) % Mod;
  100.       }
  101.    }
  102.  
  103.    inline int operator()
  104.       (const int pos, const int len, const int mx_len = -1) const
  105.       {
  106.          assert(pos + len <= sz);
  107.          int hash_int = pref_int[pos + len - 1];
  108.          if (pos != 0) {
  109.             hash_int = (hash_int - pref_int[pos - 1] + Mod) % Mod;
  110.          }
  111.          if (mx_len != -1) { // for direct comparison between prefixes
  112.             //else multiply with opposite powers
  113.             assert (mx_len < (int)pow_int.size());
  114.             hash_int = int(1ll*hash_int*pow_int[mx_len - (pos+len-1)] % Mod);
  115.          }
  116.          return hash_int;
  117.       }
  118.    //indexing from 0, len >= 1
  119. };
  120.  
  121. int polyhash::p = polyhash::gen_base((int)256, polyhash::Mod);
  122. vector <int> polyhash::pow_int{1};
  123. // int polyhash::p = 31; // 31 for [a ... z], 53 for [a..z, A..Z]
  124.  
  125. vector <string> s;
  126. pair <string, string> get_best(string &big, string &small) {
  127.    int n = (int)big.size(), m = (int)small.size();
  128.    polyhash hash_big(big), hash_small(small);
  129.  
  130.    //smaller contained inside
  131.    for (int i = 0; i  + m - 1 <= n - 1; ++i) {
  132.       if (hash_big(i, m, n) == hash_small(0, m, n)) {
  133.          return make_pair(big, big);
  134.       }
  135.    }
  136.  
  137.    int mx_len1 = 0, mx_len2 = 0;
  138.    for (int i = 0; i < m; ++i) {
  139.       //smaller shares its suffix with biggers prefix
  140.       int len1 =  m - i;
  141.       if (hash_big(0, len1, n) == hash_small(i, len1, n))
  142.          mx_len1 = max(mx_len1, len1);
  143.  
  144.       //smaller shares its prefix with biggers suffix
  145.       int len2 = i + 1;
  146.       if (hash_big(n - len2, len2, n) == hash_small(0, len2, n))
  147.          mx_len2 = max(mx_len2, len2);
  148.    }
  149.  
  150.    if (mx_len1 == 0 && mx_len2 == 0) {
  151.       return make_pair(big + small, small + big);
  152.    }
  153.    else {
  154.       if (mx_len1 > mx_len2) {
  155.          big = small.substr(0, m - mx_len1) + big;
  156.       }
  157.       else {
  158.          big = big + small.substr(mx_len2, m - mx_len2);
  159.       }
  160.       return make_pair(big, big);
  161.    }
  162. }
  163.  
  164. void solve() {
  165.    int ans = (int)(s[0].size() + s[1].size() + s[2].size());
  166.    vector <int> idx = {0, 1, 2};
  167.    do{
  168.       pair <string, string> best, ans1, ans2;
  169.       string big, small;
  170.       if (s[idx[0]].size() > s[idx[1]].size()) big = s[idx[0]], small = s[idx[1]];
  171.       else big = s[idx[1]], small = s[idx[0]];
  172.       best = get_best(big, small);
  173.  
  174.       if (best.x.size() > s[idx[2]].size()) big = best.x, small = s[idx[2]];
  175.       else big = s[idx[2]], small = best.x;
  176.       ans1 = get_best(big, small);
  177.  
  178.       if (best.y.size() > s[idx[2]].size()) big = best.y, small = s[idx[2]];
  179.       else big = s[idx[2]], small = best.y;
  180.       ans2 = get_best(big, small);
  181.  
  182.  
  183.       int local_ans = min({ans1.x.size(), ans1.y.size(), ans2.x.size(), ans2.y.size()});
  184.       ans = min(ans, local_ans);
  185.    } while (next_permutation(idx.begin(), idx.end()));
  186.  
  187.    cout << ans << '\n';
  188. }
  189.  
  190. signed main() {
  191.    IOS; PREC;
  192.    s.resize(3);
  193.    while (cin >> s[0] >> s[1] >> s[2]) {
  194.       solve();
  195.    }
  196.  
  197.    return EXIT_SUCCESS;
  198. }
Add Comment
Please, Sign In to add comment