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

思路:先用二分+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('\n');
    }
};
 
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;
}
/* ******************************************************************************** */

[hdu5340]二分,枚举,二进制压位加速的更多相关文章

  1. 压位加速-poj-2443-Set Operation

    题目链接: http://poj.org/problem?id=2443 题目意思: 有n个集合(n<=1000),每个集合有m个数ai(m<=10000,1=<ai<=100 ...

  2. POJ 2443 Set Operation(压位加速)

    http://poj.org/problem?id=2443 题意: 有1000个集合,每个集合有至多10000个数,之后输入多个询问,判断询问的两个数是否位于同一个集合. 思路: 位运算...很强大 ...

  3. HDU- 3605 - Escape 最大流 + 二进制压位

    HDU - 3605 : acm.hdu.edu.cn/showproblem.php?pid=3605 题目: 有1e5的的人,小于10个的星球,每个星球都有容量,每个人也有适合的星球和不适合的星球 ...

  4. [BZOJ5109][LOJ #6252][P4061][CodePlus 2017 11月赛]大吉大利,今晚吃鸡!(最短路+拓扑排序+传递闭包+map+bitset(hash+压位))

    5109: [CodePlus 2017]大吉大利,晚上吃鸡! Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 107  Solved: 57[Sub ...

  5. [YNOI2017][bzoj4811][luogu3613] 由乃的OJ/睡觉困难综合症 [压位+树链剖分+线段树]

    题面 BZOJ题面,比较不清晰 Luogu题面,写的比较清楚 思路 原题目 我们先看这道题的原题目NOI2014起床困难综合症 的确就是上树的带修改版本 那么我们先来解决这个原版的序列上单次询问 二进 ...

  6. 【C#进阶系列】15 枚举类型和位标志

    实际上本章就只讲枚举类型,因为位标志本来就可以当做一个特殊的枚举类型. 关于枚举类型 枚举类型是一种消灭魔法数字的好方法,使程序更容易编写,阅读和维护. 枚举类型是值类型,然而有别于其它值类型,枚举类 ...

  7. codevs 3119 高精度练习之大整数开根 (各种高精+压位)

    /* codevs 3119 高精度练习之大整数开根 (各种高精+压位) 二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in 结果:AC 内存使用量: 2 ...

  8. UOJ #314. 【NOI2017】整数 | 线段树 压位

    题目链接 UOJ 134 题解 可爱的电音之王松松松出的题--好妙啊. 首先想一个朴素的做法! 把当前的整数的二进制当作01序列用线段树维护一下(序列的第i位就是整数中位权为\(2^k\)的那一位). ...

  9. 【NOI】2017 整数(BZOJ 4942,LOJ2302) 压位+线段树

    [题目]#2302. 「NOI2017」整数 [题意]有一个整数x,一开始为0.n次操作,加上a*2^b,或询问2^k位是0或1.\(n \leq 10^6,|a| \leq 10^9,0 \leq ...

随机推荐

  1. PHP函数:array_key_exists

    array_key_exists()  - 检查数组里是否有指定的键名或索引. 注意:array_key_exists() 仅仅搜索第一维的键. 多维数组里嵌套的键不会被搜索到. 说明: rray_k ...

  2. 基于Neo4j的个性化Pagerank算法文章推荐系统实践

    新版的Neo4j图形算法库(algo)中增加了个性化Pagerank的支持,我一直想找个有意思的应用来验证一下此算法效果.最近我看Peter Lofgren的一篇论文<高效个性化Pagerank ...

  3. 【Linux常见命令】dos2unix命令,unix2dos命令

    我们都知道.打回车键就是换行的意思. 在不同系统下打回车键效果是不同的: MAC OS下:dakdhih \r LINUX下:dakdhih \n DOS\WINDOWS下:dakdhih \r\n ...

  4. mac OS vi/vim 使用教程

    vi/vim 的使用 基本上 vi/vim 共分为三种模式 分别是 命令模式(Command mode) 输入模式(Insert mode) 底线命令模式(Last line mode) 命令模式: ...

  5. bibernate中inverse和cascade用法

    一口一口吃掉Hibernate(八)--Hibernate中inverse的用法 [转自 http://blog.csdn.net/xiaoxian8023 ] 一.Inverse是hibernate ...

  6. PHP的闭包和匿名函数

    闭包函数是创建时,封装周围状态的函数,而匿名函数是没有名称的函数,匿名函数可以被赋值给变量,也就是所谓的函数式编程,也可以传递参数,经常作为回调函数.(理论上讲:匿名函数和闭包不算是一个概念,php却 ...

  7. IDC:企业需求疲软 第三季度全球服务器市场收入下滑7%

    根据IDC全球服务器季度追踪报告,2016年第三季度全球服务器市场同比减少7%至125亿美元.整个服务器市场的增长最近有所放缓,部分原因是超大规模数据中心增长放缓,以及受到高端服务器销售下滑的拖累.此 ...

  8. .NET Micro Framework 4.2 beta 源码探析

    .NET Micro Framework 4.2 beta发布已经有一段时间了,一直没有腾出时间研究,昨天因为LWIP协议栈的原因(感觉上一个版本有点问题)刚 下了代码,所以抽空研究了一下.      ...

  9. C# 基础知识系列- 14 IO篇 文件的操作 (3)

    本篇继续前两篇内容,跟大家介绍一下Path类以及FileSystemInfo这个类的主要方法和属性. 上文提到,在<C# 基础知识系列-IO篇>之文件相关的内容完结之后,会带领大家开发一个 ...

  10. 负载均衡服务之HAProxy https配置、四层负载均衡以及访问控制

    前文我们聊了下haproxy的访问控制ACL的配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12817773.html:今天我们来聊一聊haproxy的h ...