BZOJ3325: [Scoi2013]密码

https://lydsy.com/JudgeOnline/problem.php?id=3325

分析:

  • 根据前i个字符和一些不等和相等条件就可以确定每一位。
  • 用manacher优化暴力的过程,发现就是manacher逆过来做。
  • 相等的赋值,不等的打标记。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define N 200050
#define db(x) cerr<<#x<<" = "<<x<<endl
char ans[N];
int n,a[N],b[N],vis[30][N];
int rp[N];
int main() {
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<n;i++) scanf("%d",&b[i]);
int ln=2*n+1;
for(i=1;i<=n;i++) {
rp[2*i-1]=b[i-1]+1;
rp[2*i]=a[i]+1;
}
rp[2*n+1]=1; int lst=1,mx=1;
for(i=1;i<=ln;i++) {
if(i&1) ans[i]='z'+1;
else if(!ans[i]) {
for(j=0;j<26;j++) if(!vis[j][i]) {
ans[i]=j+'a'; break;
}
}
int t=max(1,min(mx-i,rp[lst*2-i]));
for(;t<=rp[i];t++) {
if(i+t-1<=ln&&i-t+1>=1) ans[i+t-1]=ans[i-t+1];
}
if(i-t+1>=1&&i+t-1<=ln) vis[ans[i-t+1]-'a'][i+t-1]=1;
if(i+rp[i]-1>mx) {
mx=i+rp[i]-1;
lst=i;
}
}
for(i=2;i<=ln;i+=2) printf("%c",ans[i]);
}

BZOJ4166: 月宫的符卡序列

https://lydsy.com/JudgeOnline/problem.php?id=4166

分析:

  • 用manacher+hash暴力建立回文树并在上面DP即可。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <tr1/unordered_map>
#include <map>
using namespace std;
using namespace std::tr1;
#define db(x) cerr<<#x<<" = "<<x<<endl
#define N 1000050
#define M 2000050
#define base 131
typedef unsigned long long ull;
char w[N];
int n,ln,head[N],to[N],nxt[N],cnt,fa[N],tot,s[M],rp[M];
int val[N],ans;
ull mi[N],h[N];
unordered_map<ull,int>mp;
inline void add(int u,int v) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
ull get_h(int l,int r) {
return h[r]-h[l-1]*mi[r-l+1];
}
int work(int l,int r) {
ull now=get_h(l,r);
int p;
if(mp.count(now)) p=mp[now];
else p=mp[now]=++tot; if(r-l+1<=1||fa[p]) return p; fa[p]=work(l+1,r-1);
add(fa[p],p);
return p;
}
void dfs(int x) {
int i;
for(i=head[x];i;i=nxt[i]) {
dfs(to[i]);
val[x]^=val[to[i]];
}
if(x!=1&&val[x]>ans) ans=val[x];
}
bool check(int l,int r) {
int i,j;
for(i=l,j=r;i<=j;i++,j--) if(w[i]!=w[j]) return 0;
return 1;
}
void solve() {
ans=0;
mp.clear();
memset(rp,0,sizeof(rp));
memset(val,0,sizeof(val));
memset(head,0,sizeof(head)); cnt=0;
memset(fa,0,sizeof(fa)); scanf("%s",w+1);
n=strlen(w+1);
int i;
for(mi[0]=i=1;i<=n;i++) {
mi[i]=mi[i-1]*base;
h[i]=h[i-1]*base+w[i];
}
mp[0]=1;
for(i=2;i<=27;i++) {
fa[i]=1; add(1,i); mp[i-2+'a']=i;
}
tot=27; int mx=1,lst=1;
for(i=1;i<=n;i++) {
s[(i<<1)-1]='{';
s[(i<<1)]=w[i];
}
s[n*2+1]='{';
ln=n*2+1; lst=mx=1;
for(i=1;i<=ln;i++) {
if(i<mx) rp[i]=min(mx-i+1,rp[lst*2-i]);
else rp[i]=1;
for(;i-rp[i]>=1&&i+rp[i]<=ln&&s[i-rp[i]]==s[i+rp[i]];rp[i]++);
int t=(rp[i])>>1;
if(i&1) {
if(i!=1&&t) {
int mid=i>>1;
val[work(mid-t+1,mid+t)]^=(mid-1);
}
}else {
if(t) {
int mid=i>>1;
val[work(mid-t+1,mid+t-1)]^=(mid-1);
}
}
if(i+rp[i]-1>mx) {
mx=i+rp[i]-1; lst=i;
}
}
dfs(1);
printf("%d\n",ans);
}
int main() {
int T;
scanf("%d",&T);
while(T--) solve();
}

2342: [Shoi2011]双倍回文

https://lydsy.com/JudgeOnline/problem.php?id=2342

分析:

  • 首先我们选择的一定是一个回文串。
  • 这个限制去掉之后,只需令它的一半也是回文串。
  • 假设对称轴左边位置为\(x\),且\(y\)能成为其一半子串的右端点的条件是\(y-rp_y\le x\)且\(y\le x+rp_x/2\) 。
  • 按\(y-rp_y\)排序然后用\(set\)维护前驱后继即可。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
#define N 1000050
char w[N],s[N];
int n,rp[N],f[N],ans,t[N];
set<int>S;
inline bool cmp(const int &x,const int &y) {return x-f[x] < y-f[y];}
int main() {
scanf("%d%s",&n,w+1);
int i,ln=n*2+1;
for(i=1;i<=n;i++) s[2*i-1]='{', s[2*i]=w[i];
s[2*n+1]='{';
int mx=1,lst=1;
for(i=1;i<=ln;i++) {
rp[i]=min(mx-i,rp[lst*2-i]);
if(!rp[i]) rp[i]=1;
for(;i-rp[i]>=1&&i+rp[i]<=ln&&s[i-rp[i]]==s[i+rp[i]];rp[i]++) ;
if(i+rp[i]-1>mx) {
mx=i+rp[i]-1, lst=i;
}
}
for(i=1;i<n;i++) {
f[i]=rp[i*2+1]>>1;
}
int j=1;
for(i=1;i<n;i++) t[i]=i;
sort(t+1,t+n,cmp);
for(i=1;i<n;i++) {
int x=i;
for(;j<n&&t[j]-f[t[j]]<=x;j++) S.insert(t[j]);
set<int>::iterator it=S.upper_bound((f[x]>>1)+x);
if(it!=S.begin()) {
--it;
ans=max(ans,((*it)-x)*4);
}
}
printf("%d\n",ans);
}

BZOJ5036: [Jsoi2014]回文串

https://lydsy.com/JudgeOnline/problem.php?id=5036

分析:

  • 先用其他字符将每个字符隔开方便统计。
  • 考虑\([l,r]\)这段区间以\(x\)为中心的回文串个数。
  • 显然这玩意等于\(min(x-l+1,rp[x],r-x+1)\)
  • 拆成两部分,每一部分用树状数组再拆开统计。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
#define N 200050
#define M 300050
char w[N],s[N];
int n,rp[N],pi[N],Q,ln;
ll ans[M];
struct A {
int id,l,r,mid;
}q[M];
struct B {
ll c[N];
void fix(int x,int v) {for(;x<=ln;x+=x&(-x)) c[x]+=v;}
ll inq(int x) {ll re=0;for(;x;x-=x&(-x)) re+=c[x]; return re;}
}t1,t2,t3;
bool cmp1(const A &x,const A &y) {return x.l<y.l;}
bool cmp2(const A &x,const A &y) {return x.r>y.r;}
bool cmp3(const int &x,const int &y) {return x-rp[x]<y-rp[y];}
bool cmp4(const int &x,const int &y) {return x+rp[x]>y+rp[y];}
int main() {
scanf("%s%d",w+1,&Q);
n=strlen(w+1);
int i; ln=2*n+1;
for(i=1;i<=n;i++) s[2*i-1]='{',s[2*i]=w[i];
s[2*n+1]='{';
int mx=1,lst=1;
for(i=1;i<=ln;i++) {
rp[i]=min(mx-i,rp[2*lst-i]);
if(!rp[i]) rp[i]=1;
for(;i-rp[i]>=1&&i+rp[i]<=ln&&s[i-rp[i]]==s[i+rp[i]];rp[i]++);
if(i+rp[i]-1>mx) {
mx=i+rp[i]-1; lst=i;
}
}
// for(i=1;i<=ln;i++) printf("%d ",rp[i]); puts("");
for(i=1;i<=Q;i++) {
scanf("%d%d",&q[i].l,&q[i].r);
q[i].l=2*q[i].l-1, q[i].r=2*q[i].r+1;
q[i].id=i; q[i].mid=(q[i].l+q[i].r)>>1;
}
sort(q+1,q+Q+1,cmp1);
for(i=1;i<=ln;i++) {
t1.fix(i,rp[i]);
pi[i]=i;
}
sort(pi+1,pi+ln+1,cmp3);
int j=1;
for(i=1;i<=Q;i++) {
for(;j<=ln&&pi[j]-rp[pi[j]]+1<q[i].l;j++) {
t1.fix(pi[j],-rp[pi[j]]);
t2.fix(pi[j],1);
t3.fix(pi[j],pi[j]);
}
ans[q[i].id]+=t1.inq(q[i].mid)-t1.inq(q[i].l-1)
- (t2.inq(q[i].mid)-t2.inq(q[i].l-1))*(q[i].l-1)
+ (t3.inq(q[i].mid)-t3.inq(q[i].l-1));
}
memset(t1.c,0,sizeof(t1.c));
memset(t2.c,0,sizeof(t2.c));
memset(t3.c,0,sizeof(t3.c));
sort(q+1,q+Q+1,cmp2);
for(i=1;i<=ln;i++) t1.fix(i,rp[i]);
sort(pi+1,pi+ln+1,cmp4);
j=1;
for(i=1;i<=Q;i++) {
for(;j<=ln&&pi[j]+rp[pi[j]]-1>q[i].r;j++) {
t1.fix(pi[j],-rp[pi[j]]);
t2.fix(pi[j],1);
t3.fix(pi[j],pi[j]);
}
ans[q[i].id]+=t1.inq(q[i].r)-t1.inq(q[i].mid)
+ (t2.inq(q[i].r)-t2.inq(q[i].mid))*(q[i].r+1)
- (t3.inq(q[i].r)-t3.inq(q[i].mid));
} for(i=1;i<=Q;i++) {
ans[q[i].id]=(ans[q[i].id]-((q[i].r-q[i].l)>>1)-1)>>1;
}
for(i=1;i<=Q;i++) printf("%lld\n",ans[i]);
}

manacher(无讲解)的更多相关文章

  1. Manacher算法讲解——字符串最长回文子串

    引 入 引入 引入 Manachar算法主要是处理字符串中关于回文串的问题的,这没什么好说的. M a n a c h e r 算 法 Manacher算法 Manacher算法 朴素 求一个字符串中 ...

  2. LCT模板(无讲解)

    怎么说呢,照着打一遍就自然理解了,再打一遍就会背了,再打一遍就会推了. // luogu-judger-enable-o2 #include<bits/stdc++.h> using na ...

  3. Miller Robbin测试模板(无讲解)

    想着费马定理和二次探测定理就能随手推了. 做一次是log2n的. #include<bits/stdc++.h> using namespace std; typedef long lon ...

  4. NTT模板(无讲解)

    #include<bits/stdc++.h>//只是在虚数部分改了一下 using namespace std; typedef long long int ll; ; ; ; ; ll ...

  5. FFT模板(无讲解)

    #include<bits/stdc++.h> using namespace std; ; const double pi=3.1415926535898; ],len; struct ...

  6. dsu on tree(无讲解)

    CF741D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 分析: 最多有一个字符出现奇数次 维护某个状态下深度的最大值,注意 ...

  7. 线性最长cover(无讲解)

    #include<bits/stdc++.h> using namespace std; ; int n,f[maxn],cover[maxn],R[maxn]; char str[max ...

  8. manacher马拉车算法

    Manacher算法讲解 总有人喜欢搞事情,出字符串的题,直接卡掉了我的40分 I.适用范围 manacher算法解决的是字符串最长回文子串长度的问题. 关键词:最长 回文 子串 II.算法 1.纯暴 ...

  9. 2021北航敏捷软工Beta阶段评分与总结

    概述 Beta 阶段评分,按照之前的规则,主要组成部分为: 博客部分,基于 Beta 阶段博客的评分(每篇正规博客 10 分,每篇 Scrum5 分,评定方式类比往年) 评审部分,基于 Beta 阶段 ...

随机推荐

  1. 14:质数因子PrimeNum

    14:题目描述 功能:输入一个正整数,按照从小到大的顺序输出它的所有质数的因子(如180的质数因子为2 2 3 3 5 ) 详细描述: 函数接口说明: public String getResult( ...

  2. 【Android】带底部指示的自定义ViewPager控件

    在项目中经常需要使用轮转广告的效果,在android-v4版本中提供的ViewPager是一个很好的工具,而一般我们使用Viewpager的时候,都会选择在底部有一排指示物指示当前显示的是哪一个pag ...

  3. DataGrid绑定Dictionary问题

    问题] 在最近的项目中使用DataGrid的DataGridCheckBoxColumn绑定了后台TagModel类的IsSelected字段,数据源是TagModel类型的Dictionary,运行 ...

  4. Objective-C中NSString转NSNumber的方法

    本文转载至 http://www.linuxidc.com/Linux/2013-02/78866.htm 在Objective-C中,以数字格式组成的字符串经常需要转换为NSNumber对象后再使用 ...

  5. 链接数据库代码封装DBDA

    <?php class DBDA { public $host = "localhost"; //服务器地址 public $uid = "root"; ...

  6. Linux 设置mysql开机启动

    linux开启启动的程序一般放在/etc/rc.d/init.d/里面,/etc/init.d/是其软连接 mysql设为linux服务 cp /usr/local/mysql/support-fil ...

  7. 【题解】kth异或和/魔改版线性基

    [题解]魔改版线性基 魔改版线性基解决此类问题. 联系线性空间的性质,我们直接可以构造出这样的基: \[ 100000 \\ 010000 \\ 000010 \\ 000001 \] 使得每个基的最 ...

  8. SP1437 Longest path in a tree(树的直径)

    应该是模板题了吧 定义: 树的直径是指一棵树上相距最远的两个点之间的距离. 方法:我使用的是比较常见的方法:两边dfs,第一遍从任意一个节点开始找出最远的节点x,第二遍从x开始做dfs找到最远节点的距 ...

  9. keras: 在构建LSTM模型时,使用变长序列的方法

    众所周知,LSTM的一大优势就是其能够处理变长序列.而在使用keras搭建模型时,如果直接使用LSTM层作为网络输入的第一层,需要指定输入的大小.如果需要使用变长序列,那么,只需要在LSTM层前加一个 ...

  10. [2017-11-21]Abp系列——T4应用:权限树定义

    本系列目录:Abp介绍和经验分享-目录 今天介绍下,如何使用T4根据json文件自动生成权限定义. 先看成果 成果是: 要新增一个权限定义时,打开Json文件,找到目标节点,加个权限定义: 生成下Co ...