Submission #1176372

#TimeUsernameProblemLanguageResultExecution timeMemory
1176372kuroudoType Printer (IOI08_printer)C++20
0 / 100
322 ms68844 KiB
#pragma GCC optimize("Ofast")
#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

#define int int64_t
using namespace std;
using namespace __gnu_pbds;

template <typename T>using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T>using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

const int N = 2e5 + 10, mod = 1e9+7;

// This isn't part of my plan
struct Trie {
    struct Node {
        static const int MX = 29;
        int children[MX] = {};
        int f = 0;
    };

    vector<Node> trie;
    Trie() {
        trie.emplace_back();
    }

    void insert(string& s) {
        int idx = 0;
        for(auto i : s) {
            int nxt = i-'a';

            if(trie[idx].children[nxt] == 0) {
                trie[idx].children[nxt] = trie.size();
                trie.emplace_back();
            }
            idx = trie[idx].children[nxt];
            trie[idx].f++;
        }
    }

    void erase(string& s) {
        int idx = 0;
        for(auto i : s) {
            int nxt = i-'a';

            idx = trie[idx].children[nxt];
            trie[idx].f--;
        }
    }

    int query(string& s) {
        int idx = 0;
        int ret{};
        for(auto i : s) {
            int nxt = i - 'a';
            if(trie[trie[idx].children[nxt]].f == 0) return 0;
            idx = trie[idx].children[nxt];
        }
        return trie[idx].f;
    }
};

map<string ,int> ans;
bool comp(string x, string y){
    if(ans[x] == ans[y]) return x.size() < y.size();
    return ans[x] < ans[y];

}
int add(long long a, int b) {
    return (a + b + mod)%mod;
}

int mul(long long a, int b) {
    return (a*b)%mod;
}
// recursive
int fp(int b, int p) {
    if(!p) return 1;
    int hp = fp(b, p >> 1);
    hp = mul(hp, hp);
    return (p&1 ? mul(hp, b) : hp);
}
//iterative
int fp2(int b,int p){
   int ret=1;
   while(p){
       if(p&1) ret=mul(ret,b);
       p>>=1;
       b = mul(b,b);
    }
    return ret;
}

int Inv(int a) {
    return fp(a, mod-2);
}

int divi(int a, int b) {
    return mul(a, Inv(b));
}
const int BN = 2, ch_offset = 'a' - 1; 
const int base[BN] = { 31, 37 }; 
int pw[N][BN], inv[N][BN]; 
 
void initPows() { 
    for (int i = 0; i < BN; i++) { 
        pw[0][i] = inv[0][i] = 1; 
        int b_inv = fp(base[i], mod - 2); 
        for (int j = 1; j < N; j++) { 
            pw[j][i] = mul(pw[j - 1][i], base[i]); 
            inv[j][i] = mul(inv[j - 1][i], b_inv); 
        } 
    } 
} 
struct Hash { 
    array<int, BN> val; 
    int sz; 
 
    Hash(array<int, BN> val = {}, int sz = 0) : val(val), sz(sz) {} 
    Hash(char c) { 
        sz = 1; 
        for (int i = 0; i < BN; i++) 
            val[i] = c - ch_offset; 
    } 
 
    bool operator<(const Hash& other) const { 
        return val < other.val; 
    } 
    bool operator==(const Hash& other) const { 
        return sz == other.sz && val == other.val; 
    } 
    Hash operator+(const Hash& other) const { 
        Hash ret; 
        for (int i = 0; i < BN; i++) 
            ret.val[i] = add(val[i], mul(other.val[i], pw[sz][i])); 
        ret.sz = sz + other.sz; 
        return ret; 
    } 
    Hash operator-(const Hash& other) const { 
        Hash ret; 
        for (int i = 0; i < BN; i++) 
            ret.val[i] = mul(add(val[i], -other.val[i]), inv[other.sz][i]); 
        ret.sz = sz - other.sz; 
        return ret; 
    } 
}; 
struct RabinKarp { 
    //1-based 
    vector<Hash> hashes; 
    RabinKarp(string& s) { 
        hashes.resize(s.size() + 1); 
        hashes[0] = Hash(); 
        for (int i = 1; i <= s.size(); i++) 
            hashes[i] = hashes[i - 1] + Hash(s[i - 1]); 
    } 
 
    Hash getHash(int l, int r) { 
        return hashes[r] - hashes[l - 1]; 
    } 
}; 
void burn() {
    initPows(); 
    int n;
    cin >> n;
    // ans = vector<int>(n);

    Trie tr;
    vector<string > v(n);

    vector<RabinKarp> hshs;
    for(int i = 0;i < n;i++) {
        cin >> v[i];
        tr.insert(v[i]);
    }
    for(int i = 0;i < n;i++) {
        for(int j = 0 ;j < v[i].size()+1;j++) {
            string cur = v[i].substr(0,j);
            ans[v[i]] = max(ans[v[i]],tr.query(cur));
        }
    }
    
    sort(v.begin(),v.end(),comp);
    for(int i = 0;i < n;i++) {
        hshs.push_back(RabinKarp(v[i]));
    } 
    int strt{};

    string prnt;
    for(int i = 0 ; i < n-1;i++) {
        string x = v[i];
        
        cerr << x << ' ' << strt << '\n';

        for(int j = strt ; j  < x.size();j++) 
            prnt+=x[j]; //cout << x[j] << '\n';
        // cout << "P\n";
        prnt +="P";
        strt = x.size();
        cerr << strt << ' ';

        for(int j = strt-1; j >= 0; j--) {
            strt--;
            if(hshs[i].getHash(1,strt+1) == hshs[i+1].getHash(1,strt+1) ) break;
            // cout << "-\n";
            prnt += "-";
        }
        cerr << strt <<'\n';
    }
    string x = v[n-1];

    for(int  i = strt+1;i < x.size();i++)
        prnt += x[i];
        // cout << x[i] << '\n';
    // cout << "P\n";
    prnt += "P";

    cout << prnt.size() << '\n';

    for(auto c: prnt)
        cout << c << '\n';
}

int32_t main() {
    ios::sync_with_stdio(false);    
    cin.tie(nullptr);

    int t{1};
    // cin >> t;
    while (t--) 
        burn();    
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...