标签:blog io ar os sp for on 2014 log
题意:
给你M,L,再给一个串str
任意截取M*L长度的连续子串
再把这个子串分成M份长度为L的连续串
使得这M份互不相同
问有几种截取方法
思路:
考虑到子串是否相等,就运用字符串hash
用到map判重和割补的办法优化
代码:
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"map"
#include"vector"
#include"string"
#define inf 0x7fffffff
#include"iostream"
using namespace std;
#define ll unsigned __int64
const ll maxn=100100;
ll hash[maxn],base[maxn],cnt[maxn*10];
char s[maxn];
void init(ll len)
{
ll seed=131;
hash[0]=0;
base[0]=1;
for(ll i=1; i<=len; i++)
{
hash[i]=hash[i-1]*seed+s[i];
base[i]=base[i-1]*seed;
}
}
ll gethash(ll L,ll R)
{
return hash[R]-hash[L-1]*base[R-L+1];
}
int main()
{
ll m,l;
while(scanf("%I64u%I64u",&m,&l)!=-1)
{
ll ans=0,lit=m*l;
scanf("%s",s+1);
ll len=strlen(s+1);
init(len);
for(ll i=1; i<=l; i++)
{
map<ll,ll>mark;
ll sum=1,ssb=0;
for(ll j=i; j<=i+lit-1; j+=l) //以首开头的 先取第一个M份
{
ll tep=gethash(j,j+l-1);
if(mark[tep]==0)
{
mark[tep]=sum++;
ssb++;
cnt[mark[tep]]=0;
}
cnt[mark[tep]]++;
}
if(ssb==m) ans++;
for(ll j=i+lit; j+l-1<=len; j+=l)
{
ll tep=gethash(j-lit,j-lit+l-1);
cnt[mark[tep]]--; //删掉第一份中长度L的串
if(cnt[mark[tep]]==0)
{
ssb--;
mark[tep]=0;
}
tep=gethash(j,j+l-1); //加上后面长度为L的串
if(mark[tep]==0)
{
mark[tep]=sum++;
ssb++;
cnt[mark[tep]]=0;
}
cnt[mark[tep]]++;
if(ssb==m) ans++;
}
}
printf("%I64u\n",ans);
}
return 0;
}
标签:blog io ar os sp for on 2014 log
原文地址:http://blog.csdn.net/wdcjdtc/article/details/41206075