HDU2459 后缀数组+RMQ
题目大意:
在原串中找到一个拥有连续相同子串最多的那个子串
比如dababababc中的abababab有4个连续的ab,是最多的
如果有同样多的输出字典序最小的那个
这里用后缀数组解决问题:
枚举连续子串的长度l , 那么从当前位置0出发每次递增l,拿 i 和 i+l 开头的后缀求一个前缀和val , 求解依靠RMQ 得到区间 rank(i),rank(i+l)
那么连续的子串个数应该是val/l+1
但是由于你不一定是从最正确的位置出发,那么我们就需要不断将这个i往前推l位,直到某一位字符不匹配,推移的过程中,可能与形成连续串多出的
部分形成一个新的子串,那么个数应该加1,且不断更新推移过程中的rank值,尽量取到rank值小的开头的字符串
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = ;
int r[N] , sa[N] , _rank[N] , height[N];
int wa[N] , wb[N] , wv[N] , wsf[N];
int cmp(int *r , int a , int b , int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(int *r , int *sa , int n , int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=;i<m;i++)wsf[i]=;
for(i=;i<n;i++)wsf[x[i]=r[i]]++;
for(i= ; i<m ; i++) wsf[i]+=wsf[i-];
for(i=n-;i>=;i--) sa[--wsf[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p){
for(p=,i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=;i<n;i++) wv[i]=x[y[i]];
for(i=;i<m;i++) wsf[i]=;
for(i=;i<n;i++) wsf[wv[i]]++;
for(i=;i<m;i++) wsf[i]+=wsf[i-];
for(i=n-;i>=;i--) sa[--wsf[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return;
}
void callHeight(int *r , int *sa , int n)
{
int i,j,k=;
for(i=;i<=n;i++) _rank[sa[i]]=i;
for(i=;i<n;height[_rank[i++]]=k)
for(k?k--:,j=sa[_rank[i]-];r[i+k]==r[j+k];k++);
return;
} int dp[N<<][] , n;
char s[N];
void ST()
{
memset(dp , 0x3f , sizeof(dp));
for(int i= ; i<=n ; i++)dp[i][]=height[i];
for(int k= ; (<<k)<=n ; k++){
for(int i= ; i<=n ; i++){
dp[i][k] = min(dp[i][k-] , dp[i+(<<(k-))][k-]);
}
}
}
int RMQ(int s , int t)
{
int d = t-s+;
int k = (int)log2(d*1.0);
// cout<<s<<" "<<t<<" "<<k<<" "<<t-(1<<k)+1<<endl;
return min(dp[s][k] , dp[t-(<<k)+][k]);
}
int RMQPOS(int x , int y)
{
// cout<<"cal pos: "<<x<<" "<<y<<" ";
x = _rank[x] , y = _rank[y];
if(x>y){int t=x;x=y,y=t;}
// cout<<x<<" "<<y<<" "<<RMQ(x+1,y)<<" ";
return RMQ(x+,y);
}
void solve(int &mxTime , int &ansl , int &ansLf)
{
ansl = ansLf = mxTime = ;
for(int l= ; l<=n/ ; l++) {//最外层循环节长度
for(int i= ; i+l<n ; i+=l){
int mxl = RMQPOS(i , i+l);
int time = mxl/l+; int del = time*l-mxl , curpos=i , mxRank=_rank[i];
int t;
for(t= ; t<l ; t++){
if(i<t || s[i-t]!=s[i+l-t]) break;
if(_rank[i-t]<mxRank){
mxRank = _rank[i-t];
curpos = i-t;
}
if(t==del){
mxRank = _rank[i-t];
curpos = i-t , time++;
}
} if(mxTime<time||(mxTime==time&&mxRank<_rank[ansLf])) mxTime=time,ansl=time*l,ansLf=curpos; }
}
}
int main()
{
//freopen("a.in" , "r" , stdin);
int cas = ;
while(scanf("%s" , s))
{
n = strlen(s);
if(n== && s[]=='#') break;
printf("Case %d: ",++cas);
for(int i= ; i<n ; i++) r[i] = s[i]-'a'+;
r[n]=;
da(r,sa,n+,);
callHeight(r,sa,n);
ST(); int mxTime , ansl , ansLf;
solve(mxTime , ansl , ansLf);
if(mxTime==){
char minc='a';
for(int i= ; i<n ; i++){
minc=min(minc , s[i]);
}
printf("%c\n" , minc);
continue;
}
for(int i= , j=ansLf ; i<ansl ; i++,j++) printf("%c" , s[j]);
puts("");
}
return ;
}
HDU2459 后缀数组+RMQ的更多相关文章
- 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过
题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...
- POJ 3693 后缀数组+RMQ
思路: 论文题 后缀数组&RMQ 有一些题解写得很繁 //By SiriusRen #include <cmath> #include <cstdio> #includ ...
- spoj687 REPEATS - Repeats (后缀数组+rmq)
A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed strin ...
- hdu 2459 (后缀数组+RMQ)
题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...
- ural 1297(后缀数组+RMQ)
题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文. 思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能 ...
- 【BZOJ 3473】 字符串 (后缀数组+RMQ+二分 | 广义SAM)
3473: 字符串 Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串 ...
- 【poj3693】Maximum repetition substring(后缀数组+RMQ)
题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...
- 【HDU3948】 The Number of Palindromes (后缀数组+RMQ)
The Number of Palindromes Problem Description Now, you are given a string S. We want to know how man ...
- BZOJ 3277: 串/ BZOJ 3473: 字符串 ( 后缀数组 + RMQ + 二分 )
CF原题(http://codeforces.com/blog/entry/4849, 204E), CF的解法是O(Nlog^2N)的..记某个字符串以第i位开头的字符串对答案的贡献f(i), 那么 ...
随机推荐
- Mysql Specified key was too long; max key length is 767 bytes
今天导入一个数据库时,看到以下报错信息: Specified key was too bytes 直译就是索引键太长,最大为767字节. 查看sql库表文件,发现有一列定义如下: 列 名:cont ...
- The communication of Linux Server and Localtion
当用Secure CRT远程登录服务器时,若建立本地与服务器间文件自由传输的机制,我们就可以实现远程办公.具体方法如下: 1. 确定远程服务器的IP.可以通过Secure CRT进行远程登录. 2.在 ...
- HDU 5980 Find Small A(寻找小A)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- 在ionic/cordova中使用极光推送插件(jpush)
Stpe1:创建一个项目(此处使用的是tab类型的项目,创建方式可参照我前一篇如何离线创建Ionic1项目) Stpe2:修改项目信息 打开[config.xml]修改下图内容:
- Linux与user和group相关文件分析
/etc/passwd LOGNAME:PASSWORD::UID:GID:USERINFO:HOME:SHELL 注册名:口令:用户标识号:组标识号:用户名:用户主目录:命令解释程序 ()注册名(l ...
- 关于content-type","application/x-www-form-urlencoded;charset=utf-8"的说明
在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型. 下边是说明: application/x-www-form-urlen ...
- javascrpt事件
1.HTML事件处理程序:就是事件直接写在HTML文档中,其特点就是HTML和Js紧密的结合在一起,缺点就是修改不方便,需要改动js和HTML两处.比如: <button onclick=&qu ...
- Mysql主从同步遇到的一些问题
为提供更快的访问速度,在不同的地区增加了一台只供访问的从服务器.因此要将主服务器的数据全部备份过去,并且设置主从同步 假设: 主服务器IP:192.168.1.10 从服务器IP:192.168.1. ...
- c3p0连接池获得的Connection执行close方法后是否真的销毁Connection对象?
问题描述: jfinal做的api系统中,在正常调用接口一段时间后,突然再调用接口的时候,该请求无响应api系统后台也无错误信息 (就是刚开始接口调用是正常的,突然就无响应了) 于是啊,就开始找错误. ...
- AE调用GP工具的方法(转)
第一,首先要明确自己需要调用arctoolbox里面的什么工具,实现什么样的功能. 第二,按照需求看看在arctoolbox工具中是怎么实现功能的,然后确定需要的数据源. 第三,编写command或t ...