zoukankan      html  css  js  c++  java
  • [hdu5340]二分,枚举,二进制压位加速

     题意:判断一个字符串能否划成三段非空回文串。

    思路:先用二分+hash在nlogn的时间内求出以每条对称轴为中心的回文串的最大半径r[i](可以用对称的两个下标之和来表示 ),然后利用r[i]求出pre[i]和suf[i],其中pre[i]表示0~i能否形成回文串,suf[i]表示i~n-1能否形成回文串。然后枚举中间的第二段回文串的对称轴,利用半径r[i]得到最左端L和最右端R,问题变成能否找到一个数d,使得pre[L+d] && suf[R-d],-1<=d,L+d<R-d,这显然可以用二进制来加速,移位,按位与,判断是否为0等操作都降低了常数倍复杂度。理论上复杂度变为O(n^2/64),实际上跑起来慢爆了,可能是写挫了TUT......

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    /* ******************************************************************************** */
    #include <iostream>                                                                 //
    #include <cstdio>                                                                   //
    #include <cmath>                                                                    //
    #include <cstdlib>                                                                  //
    #include <cstring>                                                                  //
    #include <vector>                                                                   //
    #include <ctime>                                                                    //
    #include <deque>                                                                    //
    #include <queue>                                                                    //
    #include <algorithm>                                                                //
    #include <map>                                                                      //
    #include <cmath>                                                                    //
    using namespace std;                                                                //
                                                                                        //
    #define pb push_back                                                                //
    #define mp make_pair                                                                //
    #define X first                                                                     //
    #define Y second                                                                    //
    #define all(a) (a).begin(), (a).end()                                               //
    #define fillchar(a, x) memset(a, x, sizeof(a))                                      //
                                                                                        //
    typedef pair<intint> pii;                                                         //
    typedef long long ll;                                                               //
    typedef unsigned long long ull;                                                     //
                                                                                        //
    #ifndef ONLINE_JUDGE                                                                //
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}    //
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>                    //
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;          //
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>      //
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>              //
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>   //
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}   //
    #endif // ONLINE_JUDGE                                                              //
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}        //
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}        //
    template<typename T>                                                                //
    void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}            //
    template<typename T>                                                                //
    void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}            //
                                                                                        //
    const double PI = acos(-1.0);                                                       //
    const int INF = 1e9 + 7;                                                            //
                                                                                        //
    /* -------------------------------------------------------------------------------- */
     
    unsigned long long Pre[64], Suf[64];
    struct BitSet {
        vector<unsigned long long> s;
        static void init() {
            Pre[0] = 1;
            Suf[63] = (unsigned long long)1 << 63;
            for (int i = 1; i < 64; i ++) {
                Pre[i] = (unsigned long long)1 << i | Pre[i - 1];
            }
            for (int i = 62; i >= 0; i --) {
                Suf[i] = (unsigned long long)1 << i | Suf[i + 1];
            }
        }
        void resize(int n) {
            int p = s.size(), t = (n - 1) / 64 + 1;
            s.resize(t);
        }
        BitSet(int n) {
            resize(n);
        }
        BitSet() {}
        BitSet operator & (BitSet &that) {
            int sz = that.s.size(), n = this->s.size(), len = max(sz, n);
            if (sz < len) that.resize(len);
            if (n < len) this->resize(len);
            BitSet ans(len * 64);
            for (int i = len - 1; i >= 0; i --) {
                ans.s[i] = this->s[i] & that.s[i];
            }
            return ans;
        }
        BitSet operator | (BitSet &that) {
            int sz = that.s.size(), n = this->s.size(), len = max(sz, n);
            if (sz < len) that.resize(len);
            if (n < len) this->resize(len);
            BitSet ans(len * 64);
            for (int i = len - 1; i >= 0; i --) {
                ans.s[i] = this->s[i] | that.s[i];
            }
            return ans;
        }
        BitSet operator ^ (BitSet &that) {
            int sz = that.s.size(), n = this->s.size(), len = max(sz, n);
            if (sz < len) that.resize(len);
            if (n < len) this->resize(len);
            BitSet ans(len * 64);
            for (int i = len - 1; i >= 0; i --) {
                ans.s[i] = this->s[i] ^ that.s[i];
            }
            return ans;
        }
        BitSet operator << (int x) {
            int sz = s.size(), c = x / 64, r = x % 64;
            BitSet ans(64 * sz);
            for (int i = sz - 1; i - c >= 0; i --) {
                ans.s[i] = (s[i - c] & Pre[63 - r]) << r;
                if (r && i - c - 1 >= 0) ans.s[i] |= (s[i - c - 1 ] & Suf[64 - r]) >> (64 - r);
            }
            return ans;
        }
        BitSet operator >> (int x) {
            int sz = s.size(), c = x / 64, r = x % 64;
            BitSet ans(64 * sz);
            for (int i = 0; i + c < sz; i ++) {
                ans.s[i] = (s[i + c] & Suf[r]) >> r;
                if (r && i + c + 1 < sz) ans.s[i] |= (s[i + c + 1] & Pre[r - 1]) << (64 - r);
            }
            return ans;
        }
        bool get(int p) {
            int c = p / 64, r = p % 64;
            return s[c] & ((unsigned long long)1 << r);
        }
        bool zero() {
            int n = s.size();
            for (int i = 0; i < n; i ++) {
                if (s[i]) return false;
            }
            return true;
        }
        void setval(int L, int R, bool val) {
            int p = L / 64, tp = L % 64, q = R / 64, tq = R % 64;
            for (int i = p + 1; i < q; i ++) {
                s[i] = val? ((unsigned long long)-1) : 0;
            }
            if (p == q) {
                unsigned long long buf = Suf[tp] & Pre[tq];
                s[p] = val? s[p] | buf : s[p] & ~buf;
                return ;
            }
            s[p] = val? s[p] | Suf[tp] : s[p] & ~Suf[tp];
            s[q] = val? s[q] | Pre[tq] : s[q] & ~Pre[tq];
        }
        void print() {
            int n = s.size();
            for (int i = n - 1; i >= 0; i --) {
                unsigned long long x = s[i];
                for (int i = 63; i >= 0; i --) {
                    if (((unsigned long long)1 << i) & x)
                        putchar('1');
                    else
                        putchar('0');
                }
            }
            putchar(' ');
        }
    };
     
    struct StringHash {
        const static unsigned int hack = 1301;
        const static int maxn = 1e5 + 7;
        unsigned long long H[maxn], C[maxn];
        void init(char s[], int n) {
            for (int i = 0; s[i]; i ++) {
                H[i] = (i? H[i - 1] * hack : 0) + s[i];
            }
            C[0] = 1;
            for (int i = 1; i <= n; i ++) C[i] = C[i - 1] * hack;
        }
        unsigned long long get(int L, int R) {
            return H[R] - (L? H[L - 1] * C[R - L + 1] : 0);
        }
    } ;
    StringHash hsh, hshrev;
    const int maxn = 1e5 + 7;
    bool pre[maxn], suf[maxn];
    char s[maxn], revs[maxn];
    int F[maxn];
     
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt""r", stdin);
    #endif // ONLINE_JUDGE
        BitSet::init();
        int T;
        cin >> T;
        while (T --) {
            scanf("%s", s);
            int n = strlen(s), total = n * 2 - 1;
            hsh.init(s, n);
            for (int i = 0; i < n; i ++) revs[i] = s[n - i - 1];
            hshrev.init(revs, n);
            for (int i = 0; i < total; i ++) {
                int L = i / 2, R = (i + 1) / 2;
                int minlen = 0, maxlen = min(L + 1, n - R);
                while (minlen < maxlen) {
                    int midlen = (minlen + maxlen + 1) >> 1;
                    int lpos = L - midlen + 1, rpos = R + midlen - 1;
                    if (hsh.get(lpos, L) == hshrev.get(n - rpos - 1, n - R - 1)) minlen = midlen;
                    else maxlen = midlen - 1;
                }
                F[i] = minlen;
            }
     
            fillchar(pre, 0);
            fillchar(suf, 0);
            pre[0] = suf[n - 1] = true;
            BitSet bs1(n), bs2(n);
            bs1.setval(0, 0, 1);
            bs2.setval(0, 0, 1);
            for (int i = 1; i < n; i ++) {
                pre[i] = F[i] == i / 2 + 1;
                if (pre[i]) bs1.setval(i, i, 1);
            }
            for (int i = n - 2; i >= 0; i --) {
                suf[i] = F[i + n - 1] == (n - i + 1) / 2;
                if (suf[i]) bs2.setval(n - i - 1, n - i - 1, 1);
            }
     
            bool ok = false;
            for (int i = 0; i < total; i ++) {
                int L = i / 2, R = (i + 1) / 2;
                int len = F[i], lpos = L - len + 1, rpos = R + len - 1;
                if (len == 0) continue;
                BitSet buf, result, newbuf(n);
                if (n - R >= L + 1) {
                    buf = bs2 >> (n - R - L - 1);
                    result = bs1 & buf;
                    newbuf.setval(max(0, lpos - 1), L - 1, 1);
                }
                if (L + 1 > n - R) {
                    buf = bs1 >> (L + 1 - n + R);
                    result = buf & bs2;
                    newbuf.setval(max(0, n - rpos - 2), n - R - 2, 1);
                }
                newbuf = newbuf & result;
                if (!newbuf.zero()) {
                    ok = true;
                    break;
                }
            }
            puts(ok? "Yes" "No");
        }
        return 0;
    }
    /* ******************************************************************************** */

  • 相关阅读:
    浅谈管道模型(Pipeline)
    经常使用的webservice接口
    2012年终总结
    【Linux】linux经常使用基本命令
    php:兄弟连之面向对象版图形计算器1
    学习selenium所须要具备的技术
    Sftp和ftp 差别、工作原理等(汇总ing)
    对数据分布进行可视化的方法
    FusionCharts简单教程(一)---建立第一个FusionCharts图形
    闭包和柯里化
  • 原文地址:https://www.cnblogs.com/jklongint/p/4695077.html
Copyright © 2011-2022 走看看