답안 #47206

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
47206 2018-04-29T06:13:14 Z evenharder 회문 (APIO14_palindrome) C++11
73 / 100
1000 ms 69232 KB
#include <iostream>
#include <ios>
#include <algorithm>
#include <string>
#include <vector>
#include <array>
#include <stack>

const int MAX_N = 600006;
std::vector<int> make_sa(const std::string& s)
{
    int n = s.length();
    std::vector<int> sa(n), g(n+1), ng(n+1);

    for(int i=0;i<n;i++)
    {
        sa[i] = i;
        g[i] = s[i];
    }
    g[n] = 0;

    int lim = std::max(128, n+1);
    for(int t=1;t<s.length();t<<=1)
    {
        auto cmp = [&] (int a, int b) {
            return g[a] != g[b] ? g[a] < g[b] : g[a+t] < g[b+t];
        };

        std::vector<int> cnt(lim), ind(lim+1);

        for(int i=0;i<n;i++) cnt[g[std::min(i+t, n)]]++;
        for(int i=1;i<lim;i++) cnt[i] += cnt[i-1];
        for(int i=n-1;i>=0;i--) ind[--cnt[g[std::min(i+t, n)]]] = i;

        for(int i=0;i<lim;i++) cnt[i] = 0;

        for(int i=0;i<n;i++) cnt[g[i]]++; // same as cnt[g[ind[i]]]++
        for(int i=1;i<lim;i++) cnt[i] += cnt[i-1];
        for(int i=n-1;i>=0;i--) sa[--cnt[g[ind[i]]]] = ind[i];

        ng[sa[0]] = 1;

        for(int i=1;i<n;i++)
        {
            ng[sa[i]] = ng[sa[i-1]];
            if(cmp(sa[i-1], sa[i])) ng[sa[i]]++;
        }
        g = ng;
    }
    return sa;
}

std::vector<int> make_lcp(const std::string& s, const std::vector<int>& sa)
{
    int n = s.length();
    std::vector<int> lcp(n-1);
    std::vector<int> rank(n);
    for(int i=0;i<n;i++)
        rank[sa[i]] = i;

    int len = 0;
    for(int i=0;i<n;i++)
    {
        if(rank[i])
        {
            int j = sa[rank[i]-1];
            int len_cap = n - std::max(i,j);
            while(len < len_cap && s[i+len] == s[j+len]) len++;
            lcp[rank[i]-1] = len;
        }
        if(len) len--;
    }
    return lcp;
}
long long int get_max_area(const std::vector<int>& v)
{
    std::stack<int> sh, sx;
    int n = v.size();
    long long int ans = 0;
    for(int i=0;i<=n;i++)
    {
        int val = i < n ? v[i] : 0;
        int last_x = i;
        while(!sh.empty() && sh.top() >= val)
        {
            ans = std::max(ans, 1LL * sh.top() * (i-sx.top()+1));
            last_x = sx.top();
            sh.pop();
            sx.pop();
        }
        sh.push(val);
        sx.push(last_x);
    }
    return ans;
}
std::string make_appended_str(const std::string& s)
{
    std::vector<char> v;
    for(int i=0;i<=s.length();i++)
    {
        v.push_back('_');
        if(i != s.length()) v.push_back(s[i]);
    }
    return std::string(v.begin(), v.end());
}
std::vector<int> manacher(const std::string& s)
{
    std::vector<int> ret(s.length());
    int r = -1;
    int p = -1;
    for(int i=0;i<s.length();i++)
    {
        if(i <= r) ret[i] = std::min(r-i, ret[2*p-i]);
        while(ret[i]+1 <= i && i+ret[i]+1 < s.length() &&
            s[i-ret[i]-1] == s[i+ret[i]+1])
                ret[i]++;
        if(i + ret[i] > r)
            r = i + ret[i], p = i;
    }
    return ret;
}

int spl[MAX_N+1];
int sp[20][MAX_N];
void set_sp(std::vector<int>& lcp)
{
    int n = lcp.size();
    for(int j=0;j<n;j++)
        sp[0][j] = lcp[j];
    for(int i=1;i<20;i++)
    {
        for(int j=1;j<=(1<<i);j++)
        {
            if((1<<i)+j <= MAX_N) spl[(1<<i)+j] = i;
        }
    }
    for(int i=0;i<19;i++)
    {
        for(int j=0;j<n;j++)
        {
            sp[i+1][j] = std::min(sp[i][j], sp[i][std::min(j+(1<<i), n-1)]);
        }
    }
}

long long int solve(std::string& s)
{
    std::string s_ = make_appended_str(s);
    std::vector<int> sa = make_sa(s_);
    std::vector<int> rank(sa.size());
    for(int i=0;i<sa.size();i++)
        rank[sa[i]] = i;
    std::vector<int> lcp = make_lcp(s_, sa);
    std::vector<int> ma = manacher(s_);

    set_sp(lcp);
    auto lcp_val = [&] (int x, int y)
    {
        x = rank[x];
        y = rank[y];
        if(x>y) std::swap(x,y);
        int len = y-x;
        int res = std::min(sp[spl[len]][x], sp[spl[len]][y-(1<<spl[len])]);
        return res;
    };
    auto cmp = [&] (int x, int y)
    {
        int clen = std::min({lcp_val(x,y), ma[x]+1, ma[y]+1});
        char chx = clen <= ma[x] /*&& x+clen < s_.length()*/ ? s_[x+clen] : 0;
        char chy = clen <= ma[y] /*&& y+clen < s_.length()*/ ? s_[y+clen] : 0;
        return (chx != chy ? chx < chy : x<y);
    };
    std::vector<int> ord(s_.length());
    for(int i=0;i<s_.length();i++)
        ord[i] = i;

    s_.push_back('\0');
    std::sort(ord.begin(), ord.end(), cmp);

    std::vector<int> lcp_palin;
    for(int i=1;i<ord.size();i++)
    {
        int v = std::min({
            ma[ord[i-1]],
            ma[ord[i]],
            lcp_val(ord[i-1], ord[i])-1});
        lcp_palin.push_back(std::max(v,0));
    }

    return std::max(get_max_area(lcp_palin), (long long int)*std::max_element(ma.begin(), ma.end()));
}
int main()
{
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);
    std::string s;
    std::cin >> s;
    std::cout << solve(s);
}

Compilation message

palindrome.cpp: In function 'std::vector<int> make_sa(const string&)':
palindrome.cpp:23:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int t=1;t<s.length();t<<=1)
                 ~^~~~~~~~~~~
palindrome.cpp: In function 'std::__cxx11::string make_appended_str(const string&)':
palindrome.cpp:99:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<=s.length();i++)
                 ~^~~~~~~~~~~~
palindrome.cpp:102:14: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         if(i != s.length()) v.push_back(s[i]);
            ~~^~~~~~~~~~~~~
palindrome.cpp: In function 'std::vector<int> manacher(const string&)':
palindrome.cpp:111:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<s.length();i++)
                 ~^~~~~~~~~~~
palindrome.cpp:114:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         while(ret[i]+1 <= i && i+ret[i]+1 < s.length() &&
                                ~~~~~~~~~~~^~~~~~~~~~~~
palindrome.cpp: In function 'long long int solve(std::__cxx11::string&)':
palindrome.cpp:151:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<sa.size();i++)
                 ~^~~~~~~~~~
palindrome.cpp:174:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<s_.length();i++)
                 ~^~~~~~~~~~~~
palindrome.cpp:181:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=1;i<ord.size();i++)
                 ~^~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 2808 KB Output is correct
2 Correct 5 ms 2920 KB Output is correct
3 Correct 4 ms 2920 KB Output is correct
4 Correct 4 ms 2988 KB Output is correct
5 Correct 5 ms 2988 KB Output is correct
6 Correct 4 ms 3040 KB Output is correct
7 Correct 4 ms 3176 KB Output is correct
8 Correct 4 ms 3176 KB Output is correct
9 Correct 4 ms 3176 KB Output is correct
10 Correct 5 ms 3176 KB Output is correct
11 Correct 4 ms 3176 KB Output is correct
12 Correct 5 ms 3176 KB Output is correct
13 Correct 4 ms 3176 KB Output is correct
14 Correct 4 ms 3176 KB Output is correct
15 Correct 4 ms 3176 KB Output is correct
16 Correct 4 ms 3176 KB Output is correct
17 Correct 4 ms 3176 KB Output is correct
18 Correct 4 ms 3176 KB Output is correct
19 Correct 5 ms 3176 KB Output is correct
20 Correct 5 ms 3176 KB Output is correct
21 Correct 4 ms 3176 KB Output is correct
22 Correct 5 ms 3176 KB Output is correct
23 Correct 4 ms 3176 KB Output is correct
24 Correct 5 ms 3176 KB Output is correct
25 Correct 5 ms 3176 KB Output is correct
26 Correct 5 ms 3176 KB Output is correct
27 Correct 5 ms 3176 KB Output is correct
28 Correct 5 ms 3176 KB Output is correct
29 Correct 4 ms 3176 KB Output is correct
30 Correct 5 ms 3176 KB Output is correct
31 Correct 5 ms 3176 KB Output is correct
32 Correct 4 ms 3176 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 3248 KB Output is correct
2 Correct 7 ms 3324 KB Output is correct
3 Correct 5 ms 3324 KB Output is correct
4 Correct 6 ms 3324 KB Output is correct
5 Correct 5 ms 3324 KB Output is correct
6 Correct 7 ms 3324 KB Output is correct
7 Correct 6 ms 3324 KB Output is correct
8 Correct 6 ms 3324 KB Output is correct
9 Correct 7 ms 3324 KB Output is correct
10 Correct 5 ms 3324 KB Output is correct
11 Correct 6 ms 3324 KB Output is correct
12 Correct 6 ms 3324 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 5300 KB Output is correct
2 Correct 19 ms 5336 KB Output is correct
3 Correct 16 ms 5336 KB Output is correct
4 Correct 27 ms 5336 KB Output is correct
5 Correct 20 ms 5372 KB Output is correct
6 Correct 23 ms 5372 KB Output is correct
7 Correct 21 ms 5372 KB Output is correct
8 Correct 23 ms 5424 KB Output is correct
9 Correct 23 ms 5424 KB Output is correct
10 Correct 24 ms 5424 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 174 ms 24784 KB Output is correct
2 Correct 184 ms 24944 KB Output is correct
3 Correct 150 ms 24944 KB Output is correct
4 Correct 208 ms 24944 KB Output is correct
5 Correct 328 ms 24944 KB Output is correct
6 Correct 297 ms 24944 KB Output is correct
7 Correct 230 ms 24944 KB Output is correct
8 Correct 422 ms 24944 KB Output is correct
9 Correct 344 ms 24944 KB Output is correct
10 Correct 307 ms 25012 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 601 ms 69000 KB Output is correct
2 Correct 589 ms 69232 KB Output is correct
3 Correct 501 ms 69232 KB Output is correct
4 Correct 631 ms 69232 KB Output is correct
5 Execution timed out 1094 ms 69232 KB Time limit exceeded
6 Halted 0 ms 0 KB -