链接在此镇楼。。http://poj.org/problem?id=3261
题意 给出一个数字串的长度N以及条件参数K,然后给出数字串,求出最长子串使得其出现次数超过K。思路 二分枚举子串长度,用hash计算出每个位置开始,长度固定的hash值,放入数组中,查找出现次数,如果大于K输出当前长度,否则二分继续。。
表示不会敲二分。。。。。查找也出了问题。。。还因为没注意多case WA。。QAQ
又到了一年一度贴代码的季节了。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef unsigned long long ll;
int base=11;
int N,K;
int word[20010]={0};
ll hash_num[20010];
ll xp[20010];
ll ans[20010];
void get_hash()
{
int i;
hash_num[N]=0;
for(i=N-1;i>=0;i--)
hash_num[i]=hash_num[i+1]*base+word[i]-'0';
}
bool hash(int x)
{
int i;
for(i=0;i<=N-x;i++)
{
ans[i]=hash_num[i]-hash_num[i+x]*xp[x];
}
sort(ans,ans+N-x+1);
int temp=ans[0];
int cou=1;
for(i=1;i<=N-x;i++)
{
if(ans[i]==ans[i-1])
{
cou++;
}
else cou=1;
if(cou>=K)
return true;
}
return false;
}
int dithotomie(int s,int e)
{
while(s<e)
{
//cout<<s<<' '<<e<<endl;
int mid=((s+e)>>1)+1;
//cout<<mid<<endl;
if(hash(mid))
{
s=mid;
//cout<<e<<endl;
}
else
{
e=mid-1;
//cout<<s<<endl;
}
}
return e;
}
int main()
{
int i;
xp[0]=1;
for(i=1;i<20010;i++)
xp[i]=xp[i-1]*base;
while(~scanf("%d%d",&N,&K)){
cnt=0;
for(i=0;i<N;i++)
scanf("%d",&word[i]);
get_hash();
//cout<<1<<endl;
int start,ed;
start=1;
ed=N;
int ans=dithotomie(1,N);//二分~
printf("%d\n",ans);
}
return 0;
}
求不喷。。