http://poj.org/problem?id=3693

题意:给出一串字符,需要求这串字符中的最长重复子串,要是有多个,输出字典序最小的.........

我自己的一些想法:这个思路我一开始倒是没有看明白,慢慢的编下去,才懂了它到底是如何操作的......其实就是枚举多少个字符会匹配,然后求出它们的height值,再用这个值去除以长度,得到有多少个循环........具体看代码

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define min(x,y) x>y? y:x
#define maxn 100010
int dp[maxn][33];
int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
int rank[maxn],height[maxn],s[maxn];
char str[maxn];
int cmp(int *r,int a,int b,int k)
{
return r[a]==r[b]&&r[a+k]==r[b+k];
}
void getsa(int *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) wsf[i]=0;
for(i=0;i<n;i++) wsf[x[i]=r[i]]++;
for(i=1;i<m;i++) wsf[i]+=wsf[i-1];
for(i=n-1;i>=0;i--) sa[--wsf[x[i]]]=i;
p=1;
j=1;
for(;p<n;j*=2,m=p)
{
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) wsf[i]=0;
for(i=0;i<n;i++) wsf[wv[i]]++;
for(i=1;i<m;i++) wsf[i]+=wsf[i-1];
for(i=n-1;i>=0;i--) sa[--wsf[wv[i]]]=y[i];
t=x;
x=y;
y=t;
x[sa[0]]=0;
for(p=1,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
}
}
void getheight(int *r,int n)
{
int i,j,k=0;
for(i=1;i<=n;i++) rank[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k)
k--;
else
k=0;
j=sa[rank[i]-1];
while(r[i+k]==r[j+k])
k++;
height[rank[i]]=k;
}
}
void rmq_init(int n)
{
for(int i=1;i<=n;i++) dp[i][0]=height[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int ll,int rr)
{
int k=0;
ll=rank[ll]; //在这个地方总是出错,需要注意的是,height数组里面的值是后缀的字典序,所以在查找的时候,
rr=rank[rr]; //需要找到其排名,而不是其坐标.......
if(ll>rr)
{
int tmp=ll;
ll=rr;
rr=tmp;
}
ll++;
while((1<<(k+1))<=rr-ll+1) k++;
return min(dp[ll][k],dp[rr-(1<<k)+1][k]);
}
int main()
{
int text=0;
while(scanf("%s",str)>0)
{
if(str[0]=='#')
break;
int len=strlen(str);
for(int i=0;i<len;i++)
s[i]=str[i]-'a'+1;
s[len]=0;
getsa(s,sa,len+1,30);
getheight(s,len);
rmq_init(len);
int ans=0,pos=0,lenn;
for(int i=1;i<=len/2;i++)
{
for(int j=0;j<len-i;j+=i)
{
if(str[j]!=str[j+i])
continue;
int k=rmq(j,j+i);
int tol=k/i+1;
//printf("%d\n",tol);
int r=i-k%i;
int p=j;
int cnt=0;
for(int m=j-1;m>j-i&&str[m]==str[m+i]&&m>=0;m--)
{
cnt++;
if(cnt==r)
{
tol++;
p=m;
}
else
if(rank[p]>rank[m])
{
p=m;
}
}
if(ans<tol)
{
ans=tol;
pos=p;
lenn=tol*i;
}
else if(ans==tol&&rank[pos]>rank[p])
{
pos=p;
lenn=tol*i;
}
}
}
printf("Case %d: ",++text);
// printf("%d %d %d\n",ans,pos,lenn);
if(ans<2) //这里,如果字符总长度小于2,那么就在原串中找出一个最小的字符就好
{
char ch='z';
for(int i=0;i<len;i++)
if(str[i]<ch)
ch=str[i];
printf("%c\n",ch);
continue;
}
for(int i=pos;i<pos+lenn;i++)
printf("%c",str[i]);
printf("\n");
}
return 0;
}

poj3693(后缀数组)的更多相关文章

  1. Maximum repetition substring (poj3693 后缀数组求重复次数最多的连续重复子串)

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6328   Acc ...

  2. 【poj3693】Maximum repetition substring(后缀数组+RMQ)

    题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...

  3. poj3693(后缀数组)

    poj3693 题意 给出一个串,求重复次数最多的连续重复子串,输出字典序最小的. 分析 论文 例8(P21). Sparse-Table算法预处理出任意两个后缀串的LCP. code #includ ...

  4. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  5. POJ3693 Maximum repetition substring 后缀数组

    POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...

  6. 关于后缀数组的倍增算法和height数组

    自己看着大牛的论文学了一下后缀数组,看了好久好久,想了好久好久才懂了一点点皮毛TAT 然后就去刷传说中的后缀数组神题,poj3693是进化版的,需要那个相同情况下字典序最小,搞这个搞了超久的说. 先简 ...

  7. 【UVA10829】 L-Gap Substrings (后缀数组)

    Description If a string is in the form UVU, where U is not empty, and V has exactly L characters, we ...

  8. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  9. 【距离GDOI:131天】 后缀数组完毕

    用了近两周的时间,终于把罗神那篇后缀数组应用看完了,题目也写了一遍,T了无数次...详见前几篇博文... 后缀数组很重要的是那个height数组,可以用来做各种奇奇怪怪的东西...常用方法去是去二分, ...

随机推荐

  1. Ubuntu Server 13.10 安装配置图解教程

    一.Ubuntu Server 13.10系统安装 Ubuntu分为桌面版(desktop)和服务器版(Server),下面为大家介绍服务器版本Ubuntu Server 13.10的详细安装过程. ...

  2. STM32+IAP方案 实现网络升级应用固件

    关注了这个概念有些日子了,这段时间总算有机会实战==网络升级应用固件,这里记录下遇到的问题,及解决方案. 原理与网上流传的串口作为传输手段 一致:不同之处,无非我这里使用了网络设备传输.==(lwip ...

  3. XMPPFrameWork IOS 开发(三)登录

    原始地址:XMPPFrameWork IOS 开发(三) XMPP中常用对象们: XMPPStream:xmpp基础服务类 XMPPRoster:好友列表类 XMPPRosterCoreDataSto ...

  4. Jquery Validate结合QTip实现绚丽的表单验证

    相信做过前端开发的童鞋,一定都涉及到表单验证的模块设计,也定都会对Alert的粗暴提示厌恶至极.当然,我也不例外.一直期待着,一种比较优雅提示效果. 看到这,大家可能觉得Jquery Validate ...

  5. Failed to initialize storage module: user 的解决方式

    网上提供了一种解决方法就是在session_start()前把session的存储方式改为files,即加入以下一句代码 if (ini_get('session.save_handler') !== ...

  6. android:ViewPager动画总结

    设置动画的方案: 我们能够使用ViewPager的setPageTransformer方法,为ViewPager设置动画.下面是几种常见动画的演示及效果: 1.CubeInTransformer wa ...

  7. 你远比想象中强大pdf

      读后感: 序 一.强化自我认知 认识你自己 你认为什么东西是最重要的呢? 这个问题的答案就是价值观. 让定期审视人生成为习惯 除去恐惧 树立目标 二.改变思维模式 选择,记住你的选择(做决定) 巅 ...

  8. 【LeetCode】98. Validate Binary Search Tree (2 solutions)

    Validate Binary Search Tree Given a binary tree, determine if it is a valid binary search tree (BST) ...

  9. Redis总结(六)Redis配置文件全解(转载)

    前面已经写了一些关于redis 的介绍,redis 的基本功能和用法,基本上都说了,有问题的可以去看看 http://www.cnblogs.com/zhangweizhong/category/77 ...

  10. Timer Schedule参数说明

    Timer是一种定时器工具,用来在一个后台线程计划执行指定任务.它可以计划执行一个任务一次或反复多次. TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务. schedule的意 ...