您的位置:首页 > 其它

hdu 4821 滑动窗口+字符串哈希

2016-07-08 14:11 344 查看


String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2509    Accepted Submission(s): 753


Problem Description

Given a string S and two integers L and M, we consider a substring of S as “recoverable” if and only if

  (i) It is of length M*L;

  (ii) It can be constructed by concatenating M “diversified” substrings of S, where each of these substrings has length L; two strings are considered as “diversified” if they don’t have the same character for every position.

Two substrings of S are considered as “different” if they are cut from different part of S. For example, string "aa" has 3 different substrings "aa", "a" and "a".

Your task is to calculate the number of different “recoverable” substrings of S.

 

Input

The input contains multiple test cases, proceeding to the End of File.

The first line of each test case has two space-separated integers M and L.

The second ine of each test case has a string S, which consists of only lowercase letters.

The length of S is not larger than 10^5, and 1 ≤ M * L ≤ the length of S.

 

Output

For each test case, output the answer in a single line.

 

Sample Input

3 3
abcabcbcaabc

 

Sample Output

2

 

Source

2013 Asia Regional Changchun

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  5717 5716 5715 5714 5713 

 

Statistic | Submit | Discuss | Note

一个很low的hash方法,但是能过。 

一个串中所有字母对应的数字相加然后取模。

比如hash(abc)= (a-'a'+b-'a'+c-'a')  %mod;

设长度为n,对于第i个位置结尾  且长度为L的字符串 ,计算出对应的id值,使得不同字符串id值不同。

这个时候需要用hash,我用的是链地址法,vector数组模拟链地址。

外加经典的滑动窗口

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+7;
const double eps=1e-7;

const int maxn=100000;
typedef long long ll;
#define cal(x) (x-'a')
char s[maxn+10];
const int mod=10000;

int N,n;
int id[maxn+10];
vector<int >G[maxn+10];
int M,L;
bool same(int x,int y)
{
int i,j;
for( i=x,j=y ;i>=x-L+1 ;i--,j--)
{
if(s[i]!=s[j]) return false;
}
return true;
}
int getid(int x,int p)
{
int k=G[p].size();
if(k==0)
{
G[p].push_back(x);
N++;
return N-1;
}
for(int i=0;i<k;i++)
{
if(same(G[p][i],x))
return id[G[p][i]];
}
G[p].push_back(x);
N++;
return N-1;

}

void pre()
{

for(int i=0;i<mod;i++)
{
G[i].clear();
}
N=0;
int sum=0;
for(int i=1;i<L;i++)
{
sum+=cal(s[i]);
sum=(sum%mod+mod)%mod;
}
for(int i=L;i<=n;i++)
{
sum+=cal(s[i]);
if(i-L>=1) sum-=cal(s[i-L]);
sum=(sum%mod+mod)%mod;
id[i]=getid(i,sum);
}
}

void work()
{

int ans=0;
int rear,front;
for(int st=L;st<2*L;st++)
{
set<int >se;
front=st;
se.insert(id[st]);
int siz=1;
if(siz==M) ans++;
for(rear=st+L;rear<=n;rear+=L)
{
while(se.count(id[rear]) )
{
se.erase(id[front]);
front+=L;
siz--;
}
se.insert(id[rear]);siz++;

if(siz>M)
{
se.erase(id[front]);
siz--;
front+=L;
}
if(siz<M) continue;
ans++;
}

}
printf("%d\n",ans);

}
int main()
{
while(~scanf("%d%d",&M,&L))
{
scanf("%s",s+1);
n=strlen(s+1);
pre();

work();
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: