codeforces #30E Tricky and Clever Password KMP+Manacher+二分
来源:互联网 发布:前端开发算程序员吗 编辑:程序博客网 时间:2024/06/05 23:56
题目大意:给定一个字符串
除
要求最大化
首先我们发现
对于每个
我们发现随着
现在对于一个确定的
现在就是区间最长回文子串的问题了
一种做法是这样的:
首先利用Manacher算法求出以每个点为中心的最长回文半径,然后对于每次询问我们二分答案:
设询问区间为
利用ST表即可做到单次询问
我还YY出了一种SB做法:
观察这个题的所有询问,我们发现询问区间是依次包含的
因此我们可以从最小的区间开始依次拓展
每次拓展,假设当前拓展的是
这个用回文自动机+树上倍增就可以了
= =所以说是傻逼做法嘛
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 100100#define MOD 999911657#define BASE 2333using namespace std;int n,ans;char s[M],rev_s[M];int next[M],f[M],pos[M];pair<int,int> intervals[M];int log_2[M],a[M][17],_ans[M];void KMP(){ int i,fix=0; for(i=2;i<=n;i++) { while( fix && rev_s[fix+1]!=rev_s[i] ) fix=next[fix]; if( rev_s[fix+1]==rev_s[i] ) ++fix; next[i]=fix; } fix=0; for(i=1;i<=n;i++) { while( fix && rev_s[fix+1]!=s[i] ) fix=next[fix]; if( rev_s[fix+1]==s[i] ) ++fix; if( i+fix>=n ) return ; if(!pos[fix]) { pos[fix]=i; intervals[fix]=make_pair(i+1,n-fix); } }}void Manacher(){ int i,id=1,mx=1; s[0]='$'; for(i=1;i<=n;i++) { f[i]=min(mx-i+1,f[id+id-i]); while(s[i+f[i]]==s[i-f[i]]) ++f[i]; if(i+f[i]-1>mx) mx=i+f[i]-1,id=i; }}int Get_Max(int x,int y){ int len=log_2[y-x+1]; return max(a[x][len],a[y-(1<<len)+1][len]);}int Bisection(int x,int y){ int l=1,r=y-x+2>>1; while(l+1<r) { int mid=l+r>>1; if( Get_Max(x+mid-1,y-mid+1)>=mid ) l=mid; else r=mid; } return Get_Max(x+r-1,y-r+1)>=r?r:l;}int main(){ int i,j; scanf("%s",s+1);n=strlen(s+1); for(i=1;i<=n;i++) rev_s[i]=s[n-i+1]; KMP(); Manacher(); pos[0]=1;intervals[0]=make_pair(1,n); for(i=2;i<=n;i++) log_2[i]=log_2[i>>1]+1; for(i=1;i<=n;i++) a[i][0]=f[i]; for(j=1;j<=log_2[n];j++) for(i=1;i+(1<<j)-1<=n;i++) a[i][j]=max(a[i][j-1],a[i+(1<<j-1)][j-1]); for(i=0;pos[i];i++) { _ans[i]=2*Bisection(intervals[i].first,intervals[i].second)-1; if(i*2+_ans[i]>ans*2+_ans[ans]) ans=i; } if(ans==0) { cout<<1<<endl; for(i=1;i<=n;i++) if(f[i]*2-1==_ans[0]) { cout<<i-f[i]+1<<' '<<_ans[0]<<endl; return 0; } } else { cout<<3<<endl; cout<<pos[ans]-ans+1<<' '<<ans<<endl; int l=intervals[ans].first,r=intervals[ans].second; for(i=l;i<=r;i++) if( min(min(i-l,r-i)+1,f[i])*2-1==_ans[ans] ) { cout<<i-(_ans[ans]>>1)<<' '<<_ans[ans]<<endl; break; } cout<<n-ans+1<<' '<<ans<<endl; } return 0;}
- codeforces #30E Tricky and Clever Password KMP+Manacher+二分
- CodeForces 30E Tricky and Clever Password(hash+manacher)
- Codeforces 30E Tricky and Clever Password Manacher + KMP + 前缀和
- codeforces 30E 蓝桥杯 Tricky and Clever Password
- Tricky and Clever Password 【KMP+Manacher】【蓝桥杯试题】
- 蓝桥杯-Tricky and Clever Password(java)
- 算法练习——Tricky and Clever Password
- Tricky and Clever Passwordcsnd
- 算法笔记_055-蓝桥杯练习 Tricky and Clever Password (Java)
- 算法笔记_055-蓝桥杯练习 Tricky and Clever Password (Java)
- 算法笔记_055-蓝桥杯练习 Tricky and Clever Password (Java)
- codeforces 126B Password KMP
- Codeforces 126B Password(KMP)
- codeforces 126B password KMP
- CodeForces 126B Password 【kmp】
- CodeForces 126B password KMP
- Codeforces #227(Div2) E. George and Cards 贪心+二分
- Codeforces 387E George and Cards(二分+树状数组)
- Xcode控件使用笔记四:UITableView
- JNI函数签名表
- XWPFDOCUMENT java.util.zip.ZipException: oversubscribed dynamic bit lengths tree
- IM语音
- POJ 2976 Dropping tests、3111 K Best (二分搜索)
- codeforces #30E Tricky and Clever Password KMP+Manacher+二分
- 禁止android显示状态栏
- Java移位运算符详解实例——左移位运算符>>、带符号的右移位运算符>>
- 使用Afl-fuzz (American Fuzzy Lop) 进行fuzzing测试(待续)
- Octopress 搭建静态博客网站
- CarPlay/DIO: CommunicationPlugin的基本时序
- 自定义控件四:一个简单的自定义控件实例
- android数据库的基本回顾
- 转 [github技术]git/github 使用