后缀数组(不小于k个字符串中的最长子串)

LeetCode 至少有K个重复字符的最长子串 找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。 示例 1: 输入: s = "aaabb", k = 3 输出: 3 最长子串为 "aaa" ,其中 'a' 重复了 3 次。 示例 2: 输入: s = "ababbc", k = 2 输出: 5 最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 ... 阅读详情

POJ 3294 Life Forms
题意:输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得它在超过一般的DNA序列中出现。如果有多解,按照字典序从小到大输入所有解,无解输出?。
思路:把所有的都连接起来,用不同的字符隔开,求其后缀数组和height数组,然后二分长度,按照长度分组,判断是否有一组有超过一半的字符串,最后根据长度输出答案;

/*
*
* 倍增算法(n*logn)
* 待排序数组长度为n,放在0~n-1中,在最后补0
* sa为后缀数组,把后缀从小到大排序把后缀开头存起来,rank为名次数组,以i开头的后缀在所有后缀中排第几
* sa的有效值为1~n,sa[0]必为n无效
* rank的有效值为0~n-1,rank[n]必为0无效
* height的有效值为2~n,前两个为0
*
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+10;
int x[maxn],n,k;
int wa[maxn],wb[maxn],ww[maxn],wv[maxn],nn,Z=1;
char str[100010];
int pos[maxn];//记录是i位置的字符是第几个字符串的字符
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)//求的数组,得到的后缀数组,最长长度+1,数组里的最大值(一般180或者255);
{
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0; i<m; i++) ww[i]=0;
    for(i=0; i<n; i++) ww[x[i]=r[i]]++;
    for(i=1; i<m; i++) ww[i]+=ww[i-1];
    for(i=n-1; i>=0; i--) sa[--ww[x[i]]]=i; //处理长度为一的字符串,得到sa数组
    for(j=1,p=1; p<n; j*=2,m=p) //倍增法求sa
    {
        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;//利用上次的sa直接求出按第二个关键字排序
        for(i=0; i<n; i++) wv[i]=x[y[i]]; //第二关键字的排序得出第一关键字的顺序
        for(i=0; i<m; i++) ww[i]=0;
        for(i=0; i<n; i++) ww[wv[i]]++;
        for(i=1; i<m; i++) ww[i]+=ww[i-1];
        for(i=n-1; i>=0; i--) sa[--ww[wv[i]]]=y[i]; //根据第一关键字的顺序排出sa数组的顺序
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++) //更新x数组 x为rank数组
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return ;
}
int h[maxn];//也就是排名相邻的两个后缀的最长公共前缀sa[i]和sa[i-1]
int Rank[maxn];//名次数组
void get_height(int *r,int *sa,int n)//同上,n小1
{
    int k=0,i,j;
    for(int i=1; i<=n; i++) Rank[sa[i]]=i;
    for(int i=0; i<n; h[Rank[i++]]=k)
        for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++) ;
    return ;
}
int RMQ[maxn],mm[maxn],best[20][maxn];
void initRMQ(int n)//初始化RMQ
{
    for(int i=1; i<=n; i++) RMQ[i]=h[i];
    mm[0]=-1;
    for(int i=1; i<=n; i++)
        mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
    for(int i=1; i<=n; i++) best[0][i]=i;
    for(int i=1; i<=mm[n]; i++)
        for(int j=1; j+(1<<i)-1<=n; j++)
        {
            int a=best[i-1][j];
            int b=best[i-1][j+(1<<(i-1))];
            if(RMQ[a]<RMQ[b]) best[i][j]=a;
            else best[i][j]=b;
        }
}
int askRMQ(int a,int b)
{
    int t;
    t=mm[b-a+1];
    b-=(1<<t)-1;
    a=best[t][a],b=best[t][b];
    return RMQ[a]<RMQ[b]?a:b;
}
int lcp(int a,int b)//询问a,b后缀的最长公共前缀
{
    a=Rank[a],b=Rank[b];
    if(a>b) swap(a,b);
    return h[askRMQ(a+1,b)];
}
int sa[maxn],r[maxn];
int judge_Find(int l,int r)//判断从l到r这段区间是否满足条件
{
    if(r-l<=n/2) return 0;//长度不够
    int flag[110],cont=0;
    memset(flag,0,sizeof(flag));
    for(int i=l; i<r; i++)
    {
        int z=pos[sa[i]];//该字符是哪个字符串里的
        if(!flag[z]&&z!=0)//判断该字符串是否出现过
        {
            cont++;//个数加1
            flag[z]=1;//标记为出现过
        }
    }
    return cont>n/2;
}
int Find(int mid,int print)
{
    int l=0;
    for(int r=1; r<=nn; r++)
    {
        if(h[r]<mid||r==nn)//不满足分组条件
        {
            if(judge_Find(l,r))//判断前一个分组是否满足条件
            {
                if(print)//输出答案
                {
                    for(int i=sa[l]; i<sa[l]+mid; i++) printf("%c",x[i]+'a'-1);
                    printf("\n");
                }
                else return 1;
            }
            l=r;//更新左区间
        }
    }
    return 0;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        int cont=0,cnt=0;
        for(int i=0; i<n; i++)
        {
            scanf("%s",str);
            for(int j=0; j<strlen(str); j++)
            {
                pos[cont]=i+1;//给每一个字符编号,同一个字符串里的字符编号相同
                x[cont++]=str[j]-'a'+1;
            }
            x[cont++]=i+100;
        }
        pos[cont]=0;
        x[cont++]=0;
        nn=cont;
        da(x,sa,nn,300);
        get_height(x,sa,nn-1);
        if(n==1)//特判长度为一
        {
            printf("%s\n\n",str);
            continue;
        }
        if(!Find(1,0))//长度为1无解则说明无解
        {
            printf("?\n\n");
            continue;
        }
        int l=1,r=strlen(str),ans=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(Find(mid,0)) l=mid+1,ans=mid;
            else r=mid-1;
        }
        Find(ans,1);
        printf("\n");
    }
}
Codesys—Modbus RTU称重变送器通讯案例 Codesys控制器使用标准的Modbus库,与支持ModbusRTU的称重变送器进行通讯的案例 阅读详情

相关推荐

解决win11无法安装.net framework 3.5(包括.net2.0和3.0)错误代码:0x80070005

解决win11无法安装.net framework 3.5(包括.net2.0和3.0)错误代码:0x80070005

zeng699304的博客 2万+

POJ 3294 不小于k个字符串中的最长子串

将n个字符串连接起来,中间用没有出现过的字符隔开,然后求后缀数组,二分答案,进行分组,判断每组的后缀是否出现在不小于k的原串中。 #include&lt;cstdio&gt; #include&lt;algorithm&gt; #include&lt;cstring&gt; const int MAXN = 1e5+1e3; int r[MAXN]; // r 数组保存了字符串中的每个元素...

兜率工的博客 484

抖音直播间人气接口算法 抖音协议

抖音直播间人气接口算法 抖音协议 抖音算法

Q44804487的博客 1万+

POJ 3415 Life Forms 给定n个字符串,求出现在不小于k个字符串中的最长子串。

给定两个字符串A和B,求长度不小于k的公共子串的个数(可以相同) 这个题要用到手工模拟的单调栈。首先这个题如果暴力应该怎么解决。例如: 2 aaa Aaaa                                             中间加个z 他的高度数组应该是 0                                 ‘\0’ 0

但求心安的博客 495

Jetson Orin NX 单目标跟踪算法实战

本文对比了NanoTrack和MixFormerV2两种目标跟踪算法在Jetson Orin NX边缘设备上的实际表现。通过天空小目标跟踪场景测试发现,NanoTrack虽然表征能力较弱,但具有目标身份一致性强、失败模式可控、计算负担小等优势,更适合作为边缘端默认算法。MixFormerV2则适用于高速运动等特定场景。实验数据显示NanoTrack在Orin NX上可达200FPS,远高于MixFormerV2的38-120FPS。建议先采用NanoTrack构建稳定系统,后续再评估复杂算法的适用性。

karmueo46的博客 625

[事件相机1]2024CVPR:Event Stream-based Visual Object Tracking: A High-Resolution Benchmark Dataset

作者:Xiao Wang, Shiao Wang, Chuanming Tang, Lin Zhu, Bo Jiang, Yonghong Tian, Jin Tang代码:https://github.com/Event-AHU/EventVOT_Benchmark。

m0_37412775的博客 1707

POJ 3294 后缀数组:求不小于k个字符串中的最长子串

思路:先把所有的串连接成一个串,串写串之前用没出现过的字符隔开,然后求后缀;对height数组分组二分求得最长的公共前缀,公共前缀所在的串一定要是不同的,不然就不是所有串的公共前缀了,然后记下下标和长度即可。 刚开始理解错题意,然后不知道怎么写,然后看别人题解也不知道怎么意思,后面看了好久才知道题目意思理解错了。 时间四千多ms,别人才一百多ms,不知道别人怎么做的…… #include #

liwei的专栏 781

渲染TA实战:冰面效果制作分享

这里画一张图:我们可以看到,如果深度图的范围没有进过缩放,那就是0-1,但是归一化的-viewDir的向量长度为1,如果-viewDir不和表面垂直(这是绝大多数的情况),那么viewDir.z的分量就是一个不定值,我们不好确定需要走多少步,viewDir才能和底面相交。然后我们需要冰面的Alpha图:因为冰是透明物体,所以相对于Albedo,我们更需要的是一张冰面裂纹的蒙版图,这张图需要记录冰面的裂纹走向和深浅、冰封的气泡、以及因为压力或气体等原因产生的类似雾的效果。

qq_41166022的博客 1028

POJ3294 Life Forms【后缀数组(不小于 k 个字符串中的最长子串)】

题目描述: 给出k个字符串,k<=100,每个字符串长度<=1000. 求最长的子串使得它出现在>k/2个字符串中,如果有多个最长,按字典序输出。 题目分析: 将 k 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组。然后二分答案,将后缀分成若干组,判断每组的后缀是否出现在大于 k/2 个的原串中。 因为答案子串长度都是一样的所以可以用后缀数组确定字典序,...

Master.Yi的博客 249

1.嵌入式控制器EC学习,编译环境搭建

工欲善其事,必先利其器。 在学习EC相关知识之前,首先需要完成EC代码编译环境的搭建,需要如下内容: Keil C51(用于EC中C代码的编译器环境) EC源代码,我们使用从网上可以下载到的 ITE_V12.4_Update 版的代码为例进行学习 代码编辑器,这个可以根据自己的习惯选择,VS Code或者Source Insight等 Keil C51下载地址: http://www.downcc.com/soft/307131.html 下载完成后请进行破解 EC源代码 ...

qq_30135687的博客 3918

【深度学习新浪潮】气候预测模型的研发进展一览(2025年版)

模型类型核心优势适用场景不足ARIMA(统计模型)简单高效、可解释性强短期单变量预测非线性、长时依赖建模差随机森林(机器学习)多特征融合、抗噪声中短期多因素预测空间相关性、时序趋势捕捉弱LSTM(深度学习)长时依赖建模、端到端中长期时序预测物理一致性差、数据需求量大物理知情AI物理规律约束、高可靠性极端天气、长期气候变化模型复杂、计算成本高。

专注:太空算力、AI infra、异构调度、大模型成本工程 529

POJ 3294 Life Forms(不小于k个字符串中的最长子串 后缀数组)

转载请注明出处,谢谢http://blog.youkuaiyun.com/acm_cxlove/article/details/7854526       by---cxlove 题目:输出所有的不小于k个字符串的最长子串 http://poj.org/problem?id=3294  将n个字符串连成来,中间用一个不同的字符隔开,倍增算法求出后缀数组。 然后二分答案,利用height值将后缀

窝不是爱酱,喵~~~~ 2340

【Bug已解决】Anthropic tool_result 找不到对应 tool use id 解决方案

方案适用场景推荐指数每个tool_use必须生成对应tool_result最基础的原则,所有Harness都必须遵守⭐⭐⭐⭐⭐裁剪历史时成对处理实现了上下文裁剪/压缩逻辑的Harness⭐⭐⭐⭐⭐并行工具调用结果数量校验支持多工具并行调用的场景⭐⭐⭐⭐使用官方SDK高层封装不需要特别定制消息组装逻辑⭐⭐⭐⭐请求前主动校验中间件追求生产级健壮性,提前拦截问题⭐⭐⭐⭐⭐这类报错,本质上是。

一键难忘的博客 1万+

Life Forms 后缀数组 不小于k个字符串中的最长子串

其实还是没搞太懂后缀数组这玩意... 简单来说就是求解不小于k个字符串中的最长子串,k=n/2 思路:将n个字符串连起来,中间用不同且没有在字符串中出现过的字符隔开,然后求后缀数组,再二分答案,判断每组的后缀是否出现在不小于k个的原串中。 求解SA,h数组都是照搬的网上的模板。对于每组的h[i]只要其大于等于目标长度,就让计数器+1,当计数器大于n/2即符合要求。 代码如下

Odysseia的博客 316

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

poj 3294 后缀数组 多字符串中不小于 k 个字符串中的最长子串

Life Forms Time Limit:5000MS Memory Limit:65536K Total Submissions:16223 Accepted:4763 Description You may have wondered why most extraterrestrial life forms...

anuancong1219的博客 185

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)

题意: 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串。 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组。 然后二分答案,将后缀分成若干组,判断每组的后缀是否出现在不小于 k 个的原串中。 如果是大于127, char 是负数, 在计数排序的时候是会出问题的。 这题在输出上WA了很多次。最后下载了数据才找出来的。。。。 //...

weixin_30768661的博客 111

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

poj3294(不小于k个字符串中的最长子串---后缀数组)

#include #include #include #include #include #include #include                   //poj3294(不小于k个字符串中的最长子串---后缀数组) using namespace std; #define maxn 200010 using namespace std; int wa[

u012432475的专栏 457

poj 3294 ( 后缀数组 不小于 k 个字符串中的最长子串 )

题意 : 给定n个字符串 , 要求找出所有在大于n/2子

Lisz的专栏 427

poj 3294 不小于 k 个字符串中的最长子串(后缀数组+二分)

题目:http://poj.org/problem?id=3294 题意: 给定 n 个字符串,求出现在大于一半个字符串中的最长子串。 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组。然后二分答案,将后缀分成若干组,判断每组的后缀是否出现在不小于 k 个的原串中。这个做法的时间复杂度为 O(nlogn)。 #include<cstdio> #inc

HARD_UNDERSTAND 399

Life Forms (poj3294 后缀数组求 不小于k个字符串中的最长子串)

(累了,这题做了很久!) Life Forms Time Limit:5000MS Memory Limit:65536K Total Submissions:8683 Accepted:2375 Description You may have wondered why most extraterrestrial li...

weixin_34268843的博客 125

POJ Milk Patterns(后缀数组和二分)

这个题和昨天写的Musical Theme基本一样,那篇博客有后缀数组的学习,如果那个题没有写过的话,搞完了这个题可以去做一下。 题意 显然就是求最长可重复子串的长度,但是该子串重复的次数需不小于K。 思路 先求后缀树组,而后利用后缀树组求height数组(height[i]:存储排名为i和i-1的后缀子串的最长重复前缀子串长度 )。把排序后的后缀分成若干组,其中每组的后缀之间的height值都不小于k。例如,字符串为“aabaaaab”,当k=2时,后缀分成了4组如图所示 可以想到当一组内的height都

嘘...一只bug 179

acm后缀数组学习_相关题目及解答思路、

学习后缀数组是在我的老大dede先生的要求下进行的,对我现在的修行我还是十分满意的。对后缀数组的学习,还是要以理解为上策,看完了论文一定要做题,理解代码实现的细节,能够裸敲代码才算合格。如果仔细地看过模版,有些地方是值得注意的。比如,论文没有提到在调用da()时参数n的大小是原数组大小+1,且最后的元素为最小值,这也是为什么Calheight()中的rank从1开始求的原因。我刚开始就以为是论文错

imissher的专栏 630

POJ - 3294 Life Forms

传送门:POJ - 3294 (类似题目POJ - 3450) 题意:给你n个字符串,求在不小于k/2个字符串中出现过的最长子串。 题解:首先将n个字符串连起来,中间用不一样且没出现过的字符连起来(这个地方让我wa了好几发!!),然后二分字串的长度,将后缀分成若干组,判断每组的后缀是否在不小于k个的原串中出现过,数组sum记录每个最长字符串在原串中出现的位置sa[i]。 1 #...

只能过样例嘤嘤嘤的博客 253

后缀数组经典例题

后缀数组: sa[i]:表示排名第i个的首字母位置 Rank[i]:第i个数的排名 Height[i]:sa[i]和sa[i-1]的最长公共前缀 suffix(j) 和suffix(k) 的最长公共前缀为height[rank[j]+1], height[rank[j]+2], height[rank[j]+3], … ,height[rank[k]]中的最小值。

扬帆起航 1930

【后缀数组】伊芙利特之祭--总结

前几个月总结的后缀数组专题,现在贴出来吧。不可重叠重复串; 可重叠k次重复串; 不相同子串个数 最长回文子串 连续重复子串 重复次数最多的连续重复子串 最长公共子串 长度不小于k 的公共子串的个数 不小于k 个字符串中的最长子串 出现或反转后出现在每个字符串中的最长子串 3个字符串,问其中公共子串分别为1,2,3...l的有多少个 快速通...

222

算法合集之《后缀数组——处理字符串的有力工具》

后缀数组: sa[i]:表示排名第i个的首字母位置 Rank[i]:第i个数的排名 Height[i]:sa[i]和sa[i-1]的最长公共前缀 suffix(j) 和suffix(k) 的最长公共前缀为height[rank[j]+1], height[rank[j]+2], height[rank[j]+3], … ,height[rank[k]]中的最小值。 ...

diaocuiguo2493的博客 339
上一篇: 后缀数组(长度不小于k的公共子串的个数)
下一篇: 数位dp
acmer_zp
博客等级 码龄11年 18粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值