poj3294 后缀数组
2024-10-08 01:53:19
后缀数组多个字符串问题。
先求出height[]数组,然后二分求最大的长度。
但是条件需要改变。如果出现次数大于一般那就满足。然后就要解决如何判断那一段属于其中一个字符串。
所以先处理出长度。并且不断标记,如果在长度其中,将那个长度标记。那就不会出现自己与自己的相同情况了。
RE了很多次,字符串输入的时候同时存入整数,防止过大可能使字符串出现问题。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<string>
#include<map>
#define LL long long
using namespace std;
#define maxn 1110000
int max(int x,int y)
{return x>y?x:y;}
int min(int x,int y)
{return x<y?x:y;}
int wa[maxn],wb[maxn],wv[maxn],WS[maxn];
int vex[maxn],size,vis[],pre[maxn],cou;//vex存每一段的长度 size表示个数 pre存满足条件的开始位置 cou存满足的个数
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++) WS[i]=;
for(i=;i<n;i++) WS[x[i]=r[i]]++;
for(i=;i<m;i++) WS[i]+=WS[i-];
for(i=n-;i>=;i--) sa[--WS[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++) WS[i]=;
for(i=;i<n;i++) WS[wv[i]]++;
for(i=;i<m;i++) WS[i]+=WS[i-];
for(i=n-;i>=;i--) sa[--WS[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;
}
int Rank[maxn],height[maxn];
void calheight(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 r[maxn],sa[maxn];
int ok(int x,int n,int k)
{
cou=;
int i,j,ret=;
memset(vis,,sizeof(vis));
for(i=;i<=n;i++)
{
if(height[i]>=x)
{
for(j=;j<size;j++)
{
if(sa[i]>vex[j-]&&sa[i]<vex[j])//由于自己添加的并不会相同 所以只要满足在中间位置就可以
{
if(!vis[j])//如果满足就标记掉那个位置
{
vis[j]=;
ret++;
}
}
if(sa[i-]>vex[j-]&&sa[i-]<vex[j])
{
if(!vis[j])
{
vis[j]=;
ret++;
}
}
}
}
else
{
if(ret>k)
{
pre[cou++]=sa[i-]; }
ret=;
memset(vis,,sizeof(vis));
}
}
if(ret>k)
{
pre[cou++]=sa[n];
}
if(cou>)//表面有满足条件的
return ;
return ;
}
char s[maxn],c[maxn];
int main()
{
int i,n,ff=,fl;
while(cin>>n)
{
if(!n)break;
size=;
int len=;
int num=;
for(i=;i<n;i++)
{
scanf("%s",c);
int fl=strlen(c);
for(int p=;p<fl;p++)
{
r[len]=c[p];//修改了此处 过了 之前是先存在s[]中 但是会出现问题 因为100多可能字符有问题
s[len++]=c[p];
}
vex[size++]=len;
r[len]=num;
s[len++]=num++;
}
len--;
int j=len;
r[j]=;
da(r,sa,j+,);
calheight(r,sa,j);
int left,right,mid,ans=-;
left=,right=j,cou=;
while(left<=right)
{
mid=(left+right)/;
if(ok(mid,j,n/))
{
fl=cou;
ans=mid;
left=mid+;
}
else right=mid-;
}
/*for(i=1;i<=j;i++)
printf("%d ",height[i]);
printf("\n");*/
if(ff)
printf("\n");
else ff=;
if(ans<=)
{
printf("?\n");
continue;
}
//printf("%d\n",ans);
for(i=;i<fl;i++)
{
for(j=;j<ans;j++)
{
printf("%c",s[pre[i]+j]);
}
printf("\n");
}
}
}
/*
5
abcdef
bcdea
hzbcde
bcdyz
acxq
*/
最新文章
- js词法分析
- 从零开始编写自己的C#框架(4)——文档编写说明
- 新春测 kinect motor
- DDD为何叫好不叫座?兼论DCI与业务分析的方法论
- C# 使用xsd文件验证XML 格式是否正确
- 信号之sigsetjmp和siglongjmp函数
- [转]ASP.NET MVC 入门11、使用AJAX
- HDU 2509
- 12、SQL Server 行列转换
- lseek() 定位一个已经打开的文件
- Enterprise Solution 企业管理软件开发框架
- nginx反射理传apache配置 - cookie去哪儿了?
- ora2pg数据迁移
- 软考 程序员 下午考题 c语言 笔记
- Linux Ubuntu从零开始部署web环境及项目 -----部署项目 (三)
- Spring Cloud Zuul
- Log.isLoggable之一正确的使用姿势
- Phpstorm数组对齐设置
- 报错org.apache.hadoop.mapreduce.lib.input.FileSplit cannot be cast to org.apache.hadoop.mapred.FileSplit
- 一款功能强悍的web磁盘管理工具 (A powerful web disk management tools)
热门文章
- JSP四大域对象与九大内置对象
- HDFS数据读写过程
- 数组的方法之(Array.prototype.forEach() 方法)
- laravel 下载报错:Unable to guess the mime type as no guessers are available
- MySQL错误1055
- Apache-Shiro分布式环境配置(与redis集成)(转)
- python基础--常用的模块(collections、time、datetime、random、os、sys、json、pickle)
- SPSS20.O---软件安装
- thinkcmf 导航高亮制作方法(适用于多级导航)(通用)
- HDU 1690 最短路