字符串hash 自己的一点见解
来源:互联网 发布:centos安装 全选 编辑:程序博客网 时间:2024/06/10 02:02
题目
有一个口吃的外星人,说的话里包含很多重复的字符串,比如babab包含两个bab。给出这个外星人说的一句话,找出至少出现m次的最长字符串。
输入:
输入包含多组数据。每组数据第一行为整数m,第二行为一个仅包含小写字母的字符串,长度在m~40000之间。输入结束博阿直为m=0。
输出:
对于每组数据,如果不存在,则输出'none',否则输出两个整数,即最长字符串的长度及其起始位置的最大值。
样例输入:
3
baaaababababbababbab
11
baaaababababbababbab
3
cccccc
0
样例输出:
5 12
none
4 2
分析
一、
首先想到的是应该是暴力程序;
枚举串的长度,再进行验证,暴力生成所有该长度的子串匹配看是否在原串中出现过至少n次。
时间复杂度应为O(len^4)?(len 为 原串长度)
枚举长度 len 次运算,生成子串 len次运算 暴力匹配 len^2 次运算。
时间复杂度太高了,,肯定是没有能力通过40000的规模的
所以尝试怎么去优化算法。
二、
由于这是我们正在讲的例题,所以说我直接介绍运用 字符串hash 表 的做法。
和hash表 类似,将字符进行编码转译储存在hash 表中,
二分猜出 子串 长度len,, 建立所有长度为len 的 字符串 的hash 表
如果两个串对应的 hash 值相等,认为两字符串相等
PS:做题时卡了好久,,在计算hash值时,所选的乘方底数应该 尽量去选择一个素数。
这里直接附上我认为解释的比较清楚的网址,留作参考。
点击打开链接
点击打开链接
类似的,我在做题时选择使用 ull 让它自然溢出,
如果是 要 模 一个值 , 也尽量选择一个大质数
总体思路如上,代码附下
#include<cstdio>#include<cstring>#include<iostream>#include<cctype>#include<cstdlib>#include<vector>#include<cmath>#include<algorithm>#include<set>#include<map>#include<queue>#include<stack>using namespace std;typedef long long ll;typedef unsigned long long ull;void _scanf(int &x){char ch;int f=0;ch=getchar();while(!isdigit(ch)){if(ch=='-') f=1;ch=getchar();}x=0;while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}if(f) x=-x;}void _scanf(ll &x){char ch;int f=0;ch=getchar();while(!isdigit(ch)){if(ch=='-') f=1;ch=getchar();}x=0;while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}if(f) x=-x;}void _scanf(int &x,int &y){_scanf(x);_scanf(y);}void _scanf(int &x,int &y,int &z){_scanf(x,y);_scanf(z);}const int maxn=50005;const int p=7;struct data{int id;ull w;};bool cmp(data a,data b){if(a.w!=b.w) return a.w<b.w;return a.id<b.id;}ull H[maxn];ull pw[maxn];data hash[maxn];char s[maxn];int m;int pos;void ready(char *s,int p){int n=strlen(s);pw[0]=1;for(int i=1;i<=n;i++) pw[i]=pw[i-1]*p;H[n]=0;for(int i=n-1;i>=0;i--) H[i]=H[i+1]*p+s[i]-'a';}void getv(char *s,int L){int n=strlen(s);for(int i=0;i+L<=n;i++) hash[i]=(data){i,(H[i]-H[i+L]*pw[L])}; sort(hash,hash+n-L+1,cmp);}int check(int mid){getv(s,mid);int n=strlen(s);int cnt=0;pos=-1;for(int i=0;i+mid<=n;i++){if(i==0 || hash[i].w!=hash[i-1].w) cnt=0;if(++cnt>=m) pos=max(pos,hash[i].id);}return pos>=0;}void solve(){while(1){_scanf(m);if(m==0) break;scanf("%s",s);ready(s,p);if(!check(1)){printf("none\n");}else{int A=1,B=strlen(s)+1,ans=0,ansd=0,mid;while(A<=B){mid=(A+B)/2;if(check(mid)){A=mid+1;ans=mid;ansd=pos;}else{B=mid-1;}}printf("%d %d\n",ans,ansd);}}}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();}
- 字符串hash 自己的一点见解
- 关于自己对IMediaControl::Run()返回S_FALSE的一点见解
- 关于自己对IMediaControl::Run()返回S_FALSE的一点见解
- JavaScript中append()和innerHTML的一点自己见解
- THIS_MODULE的一点见解
- this的一点见解
- Map的一点见解
- 【Hash】自己对于一种字符串hash的证明(?)
- ajax自己的见解
- RecyclerView的自己见解
- 关于网络游戏的一点见解
- 对jstl的一点见解
- 关于hibernate的一点见解
- 对面试的一点见解
- IE6兼容的一点见解
- web.xml的一点见解
- 归并排序的一点见解
- 关于自己博客数量的检查及对博客的一点见解
- 如何研读一篇论文?
- soapui中文操作手册(七)----Web Service Sample Project
- Android日志系统(logging system)详解
- 设计模式之对象创建型 — Factory Method 工厂方法模式
- idea maven-deploy-plugin:2.7 报错
- 字符串hash 自己的一点见解
- C++函数参数传递的3种方式以及优缺点
- fcntl函数详解
- 安卓热更新之Nuwa实现步骤
- hive:(group by, having;order by)的使用;group by+多个字段,以及wiki说的group by两种使用限制验证
- F
- luasocket安装遇到的问题
- luasocket安装遇到的问题
- 基于百度BAE快速部署微信公众号后台服务程序