A. Non-palidromic cutting

考虑无解的情形:只能是形如$aaaaa$、$aaabaaa$、$abababa$这三种情况。

有解时,对于最小划分,答案必定是$1$或者$2$,判断整个串是否是回文串即可。

对于最大划分,设$f[i]$表示前$i$个字符的最大划分,则$f[i]=\max(f[j]+1)$,其中$[j+1,i]$有解,这里将限制放宽是因为放宽后最优解不会变化,且条件更加好判断。

可行的$j$可以根据$aaaaa$、$abababa$分奇偶得出两个上界,对于$aaabaaa$,最多只有一个$j$不可行,因此DP的同时分奇偶维护出前缀最大值和次大值即可$O(1)$转移。

时间复杂度$O(n)$。

#include<cstdio>
#include<cstring>
const int N=200010;
int n,i,j,k,x,y,f[N],g[N],dp[N],pre[N][2][2];char a[N];
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
inline int max(int a,int b){return a>b?a:b;}
bool checkNO(){
//aaaaa
if(f[n]<=1)return 1;
//aaaabaaaa
if(n&1){
//aaaabaaaa
int m=(n+1)/2;
if(f[n]==m+1&&f[m-1]<=1&&a[1]==a[n])return 1;
//ababababababa
if(g[n]<=1&&g[n-1]<=2)return 1;
}
return 0;
}
int calmin(){
for(int i=1;i<=n;i++)if(a[i]!=a[n-i+1])return 1;
return 2;
}
int main(){
scanf("%s",a+1);
n=strlen(a+1);
for(i=1;i<=n;i++){
f[i]=g[i]=i;
if(i>1&&a[i]==a[i-1])f[i]=f[i-1];
if(i>2&&a[i]==a[i-2])g[i]=g[i-2];
}
if(checkNO())return puts("-1"),0;
for(x=0;x<2;x++)for(y=0;y<2;y++)pre[0][x][y]=-N;
pre[0][0][0]=0;
for(i=1;i<=n;i++){
dp[i]=-N;
j=f[i]-2;
if(j>=0)dp[i]=pre[j][i&1][0]+1;
umin(j,max(g[i],g[i-1]-1)-1);
k=-N;
if(f[i]>2)if(i-f[i]<=f[i]-2-f[f[i]-2]&&a[i]==a[f[i]-2])k=dp[i-((i-f[i]+1)*2+1)];
if(j>=0){
if(pre[j][i&1^1][0]==k)umax(dp[i],pre[j][i&1^1][1]+1);
else umax(dp[i],pre[j][i&1^1][0]+1);
}
for(x=0;x<2;x++)for(y=0;y<2;y++)pre[i][x][y]=pre[i-1][x][y];
if(dp[i]>pre[i][i&1][0])pre[i][i&1][1]=pre[i][i&1][0],pre[i][i&1][0]=dp[i];
else umax(pre[i][i&1][1],dp[i]);
}
printf("%d %d",calmin(),dp[n]);
}

  

B. 100500 palidnromes

考虑DP,对于每个位置为结尾的回文串的长度可以划分为$O(\log n)$个等差数列,分别转移即可。

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=300010;
char s[N];int d[N][2],f[N][2];
struct P{
int d[3];
P(){}
P(int a,int b,int c){d[0]=a;d[1]=b;d[2]=c;}
int&operator[](int x){return d[x];}
}a[32],b[32],c[32];
inline void up(int f[][2],int x,int y){
if(y<=0)return;
int p=y&1;
if(f[x][p]<0)f[x][p]=y;else f[x][p]=min(f[x][p],y);
}
inline void make(int f[][2],int x,int y){if(y>0)f[x][y&1]=y;}
void MinPalindromeSpilt(char*s){
int n=strlen(s);
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
memset(d,0,sizeof d);
memset(f,0,sizeof f);
for(int i=0;i<=n;i++)d[i][0]=1000000000,d[i][1]=1000000001;
for(int ca=0,j=0;j<n;j++){
int cb=0,cc=0,r=-j-2;
for(int u=0;u<ca;u++){
int i=a[u][0];
if(i>=1&&s[i-1]==s[j])a[u][0]--,b[cb++]=a[u];
}
for(int u=0;u<cb;u++){
int i=b[u][0],d=b[u][1],k=b[u][2];
if(i-r!=d){
c[cc++]=P(i,i-r,1);
if(k>1)c[cc++]=P(i+d,d,k-1);
}else c[cc++]=P(i,d,k);
r=i+(k-1)*d;
}
if(j>=1&&s[j-1]==s[j])c[cc++]=P(j-1,j-1-r,1),r=j-1;
c[cc++]=P(j,j-r,1),ca=0;
P&h=c[0];
for(int u=1;u<cc;u++){
P&x=c[u];
if(x[1]==h[1])h[2]+=x[2];else a[ca++]=h,h=x;
}
a[ca++]=h;
if((j+1)%2==0)f[j+1][0]=j+1,f[j+1][1]=1000000001;
else f[j+1][0]=1000000000,f[j+1][1]=j+1;
for(int u=0;u<ca;u++){
int i=a[u][0],e=a[u][1],k=a[u][2];
r=i+(k-1)*e;
up(f,j+1,f[r][0]+1),up(f,j+1,f[r][1]+1);
if(k>1)up(f,j+1,d[i+1-e][0]),up(f,j+1,d[i+1-e][1]);
if(i+1-e>=0){
if(k>1)up(d,i+1-e,f[r][0]+1),up(d,i+1-e,f[r][1]+1);
else make(d,i+1-e,f[r][0]+1),make(d,i+1-e,f[r][1]+1);
}
}
}
}
int main(){
scanf("%s",s);
MinPalindromeSpilt(s);
int n=strlen(s);
for(int i=1;i<=n;i++){
int x=f[i][1],y=f[i][0];
if(x<1||x>N)x=-1;
if(y<1||y>N)y=-2;
printf("%d %d\n",x,y);
}
}

  

C. Not common palindromes

将两个串插入同一棵Palindromic Tree然后统计次数即可。

时间复杂度$O(n\log n)$。

#include<cstdio>
const int N=400010,S=26;
int Case,cas,i,j,all,son[N][S],fail[N],cnt[N][2],len[N],text[N],last,tot,ans[3];char s[N];
inline int newnode(int l){
for(int i=0;i<S;i++)son[tot][i]=0;
cnt[tot][0]=cnt[tot][1]=0,len[tot]=l;
return tot++;
}
inline int getfail(int x){
while(text[all-len[x]-1]!=text[all])x=fail[x];
return x;
}
inline void add(int w,int p){
text[++all]=w;
int x=getfail(last);
if(!son[x][w]){
int y=newnode(len[x]+2);
fail[y]=son[getfail(fail[x])][w];
son[x][w]=y;
}
cnt[last=son[x][w]][p]++;
}
int main(){
scanf("%d",&Case);
for(cas=1;cas<=Case;cas++){
newnode(0),newnode(-1);
text[0]=-1,fail[0]=1;
scanf("%s",s);
for(i=0;s[i]>='a';i++)add(s[i]-'a',0);
scanf("%s",s);
for(i=all=last=0;s[i]>='a';i++)add(s[i]-'a',1);
for(i=tot-1;~i;i--){
cnt[fail[i]][0]+=cnt[i][0];
cnt[fail[i]][1]+=cnt[i][1];
if(len[i]>0){
if(cnt[i][0]>cnt[i][1])ans[0]++;
if(cnt[i][0]==cnt[i][1]&&cnt[i][0])ans[1]++;
if(cnt[i][0]<cnt[i][1])ans[2]++;
}
}
printf("Case #%d: %d %d %d\n",cas,ans[0],ans[1],ans[2]);
for(last=tot=all=i=0;i<3;i++)ans[i]=0;
}
}

  

D. Subpalindrome pairs

正反两遍Manacher求出以每个位置为结尾/开头的回文子串个数,然后相乘即可。

时间复杂度$O(n)$。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=600010;
int n,m,i,r,p,f[N];char a[N],s[N];long long v[N],g[N],ans;
void work(){
for(i=1;i<=n;i++)s[i<<1]=a[i],s[i<<1|1]='#';
s[0]='$',s[1]='#',s[m=(n+1)<<1]='@';
for(r=p=0,f[1]=1,i=2;i<m;i++){
for(f[i]=r>i?min(r-i,f[p*2-i]):1;s[i-f[i]]==s[i+f[i]];f[i]++);
if(i+f[i]>r)r=i+f[i],p=i;
}
for(i=0;i<=n+5;i++)v[i]=0;
for(i=2;i<=n*2;i++)v[(i+1)/2]++,v[(i+f[i])/2]--;
for(i=1;i<=n+5;i++)v[i]+=v[i-1];
}
int main(){
scanf("%s",a+1);
n=strlen(a+1);
work();
for(i=0;i<=n+5;i++)g[i]=v[i];
reverse(g+1,g+n+1);
reverse(a+1,a+n+1);
work();
for(i=2;i<=n;i++)ans+=v[i-1]*g[i];
printf("%lld",ans);
}

  

E. OEIS A216264

限制条件非常强,考虑爆搜打表,用可撤销的回文树快速判断即可。

#include<iostream>
#include<string>
using namespace std;
int n,i;string f[70];
int main(){
f[1]="2";
f[2]="4";
f[3]="8";
f[4]="16";
f[5]="32";
f[6]="64";
f[7]="128";
f[8]="252";
f[9]="488";
f[10]="932";
f[11]="1756";
f[12]="3246";
f[13]="5916";
f[14]="10618";
f[15]="18800";
f[16]="32846";
f[17]="56704";
f[18]="96702";
f[19]="163184";
f[20]="272460";
f[21]="450586";
f[22]="738274";
f[23]="1199376";
f[24]="1932338";
f[25]="3089518";
f[26]="4903164";
f[27]="7728120";
f[28]="12099440";
f[29]="18825066";
f[30]="29112876";
f[31]="44767202";
f[32]="68461866";
f[33]="104153666";
f[34]="157657852";
f[35]="237510110";
f[36]="356158688";
f[37]="531729840";
f[38]="790476048";
f[39]="1170354912";
f[40]="1725978316";
f[41]="2535782098";
f[42]="3711932174";
f[43]="5414527812";
f[44]="7871216066";
f[45]="11405072346";
f[46]="16472995026";
f[47]="23719943936";
f[48]="34053444354";
f[49]="48748102876";
f[50]="69588917894";
f[51]="99071049592";
f[52]="140673083164";
f[53]="199235958260";
f[54]="281479919278";
f[55]="396717767314";
f[56]="557825677390";
f[57]="782576306282";
f[58]="1095448703190";
f[59]="1530103385844";
f[60]="2132734033216";
f[61]="2966632985826";
cin>>n;
for(i=1;i<=n;i++)cout<<f[i]<<endl;
}

 

URAL Palindromic Contest的更多相关文章

  1. Ural 1960 Palindromes and Super Abilities

    Palindromes and Super Abilities Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged ...

  2. URAL 1208 Legendary Teams Contest(DFS)

    Legendary Teams Contest Time limit: 1.0 secondMemory limit: 64 MB Nothing makes as old as years. A l ...

  3. Ural State University Internal Contest October'2000 Junior Session

    POJ 上的一套水题,哈哈~~~,最后一题很恶心,不想写了~~~ Rope Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7 ...

  4. ural 1208 Legendary Teams Contest

    题意描述:给定K支队伍,每队三个队员,不同队伍之间队员可能部分重复,输出这些队员同时能够组成多少完整的队伍: DFS,利用DFS深度优先搜索,如果该队所有队员都没有被访问过,那么将该队计入结果,再去选 ...

  5. Petrozavodsk Summer-2016. Ural FU Dandelion Contest

    A. Square Function 留坑. B. Guess by Remainder 询问$lcm(1,2,3,...,n)-1$即可一步猜出数. 计算$lcm$采用分治FFT即可,时间复杂度$O ...

  6. ural 2071. Juice Cocktails

    2071. Juice Cocktails Time limit: 1.0 secondMemory limit: 64 MB Once n Denchiks come to the bar and ...

  7. ural 2073. Log Files

    2073. Log Files Time limit: 1.0 secondMemory limit: 64 MB Nikolay has decided to become the best pro ...

  8. ural 2070. Interesting Numbers

    2070. Interesting Numbers Time limit: 2.0 secondMemory limit: 64 MB Nikolay and Asya investigate int ...

  9. ural 2069. Hard Rock

    2069. Hard Rock Time limit: 1.0 secondMemory limit: 64 MB Ilya is a frontman of the most famous rock ...

随机推荐

  1. Chrome开发者控制台操作教程

    1清空控制台 在控制台下有个clear console的按钮,点击的时候会清空控制台. 清空控制台  2让Chrome中的页面可编辑 有的时候我们需要临时改变页面上的文字,图案等信息,一种常见的方法是 ...

  2. HDU 1075 What Are You Talking About (stl之map映射)

    What Are You Talking About Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/204800 K ...

  3. dump增加的表数据

    备份mysql数据库表中,增加的部分 前提条件: 备份库和正式库表结构一样: 表名不一样可以改: 备份库:192.168.1.10 正式库:192.168.1.11 获取当前"备份" ...

  4. centos 6.8 安装git 报错

    报错信息: Can't locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl               ...

  5. loadrunner下的putty和plink

    loadrunner中是有集成plink和putty的,难怪可以通过监控机监控linux上的负载情况呢,可以通过这个命令来进行访问:C:\Program Files\Mercury\LoadRunne ...

  6. docker compose启动服务超时重启记录

    一.停docker systemctl stop docker 然后ps -aux grep docker发现有些docker进程还是存在,此时强杀存在的docker进程:ps -aux|grep d ...

  7. 启动tomcat出现Removing obsolete files from server... Could not clean server of obsolete ……错误

    在Eclipse启动tomcat出现"Removing obsolete files from server... Could not clean server of obsolete …… ...

  8. C++中全排列算法函数next_permutation的使用方法

    首先,先看对next_permutation函数的解释: http://www.cplusplus.com/reference/algorithm/next_permutation/?kw=next_ ...

  9. oracle中

    select tmp_tb.*, ROWNUM row_id from (SELECT MX.*                                          --这里不能直接用* ...

  10. URAL 1989 Subpalindromes (多项式hash) +【线段树】

    <题目链接> <转载于 >>>  > 题目大意:给你一段字符串,进行两种操作:1.询问[l,r]这个区间中的字符串是否是回文串: 2.更改该字符串中对应下标的 ...