HDU2087 剪花布条 \text{HDU2087 剪花布条} HDU2087 剪花布条
典型的字符串匹配问题。
网上KMP的解法太多了,我就来一发Hash哈希算法吧。
预处理:
幂
Power[0]=1;
for(register int i=1;i<=1000;i++)
Power[i]=Power[i-1]*Base%mod;
先预先算出 B 1 − B 1001 B^{1}-B^{1001} B1−B1001的值,在Hash的过程会方便一些。(B是基数,此处取1000007)
主串Hash
inline void Init(int len)
{
Hash[0]=0;
register int i;
for(i=1;i<=len;i++)
Hash[i]=(Hash[i-1]*Base%mod+(Main[i]-'A'+1)%mod)%mod;
return;
}
Hash[i]
主串
1
−
i
1-i
1−i位的Hash值。
我们通过这个公式计算哈希值:
H
(
C
[
1...
i
]
)
=
(
H
(
C
[
1...
i
−
1
]
∗
B
+
C
i
)
)
H(C[1...i])=(H(C[1...i-1]*B+C_i))
H(C[1...i])=(H(C[1...i−1]∗B+Ci))
即
H
(
C
)
=
(
C
1
×
B
n
+
C
2
×
B
n
−
1
+
.
.
.
+
C
n
×
B
)
H(C)=(C_1\times B^n+C_2\times B^{n-1}+...+C^n\times B)
H(C)=(C1×Bn+C2×Bn−1+...+Cn×B)
获取主串中部分的Hash值
inline ull Get_Hash(int L,int R)
{
return Hash[R]%mod-Hash[L-1]*Power[R-L+1]%mod;
}
根据Hash的公式,截取主串中
L
.
.
R
L..R
L..R的Hash值。
如此不断右移,对比Hash值,就可以知道字符串匹配了。
完整代码:
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ull;
const int Base=1000007;
const int mod=1e9+7;
ull Power[1001];
ull Hash[1001];
char Main[1001],Model[1001];
inline void Init(int len)
{
Hash[0]=0;
register int i;
for(i=1;i<=len;i++)
Hash[i]=(Hash[i-1]*Base%mod+(Main[i]-'A'+1)%mod)%mod;
return;
}
inline ull Get_Hash(int L,int R)
{
return Hash[R]%mod-Hash[L-1]*Power[R-L+1]%mod;
}
inline int Count()
{
register int i;
int len1=strlen(Main+1);
int len2=strlen(Model+1);
ull H_model=0;
Init(len1);
int result=0;
for(i=1;i<=len2;i++)
H_model=(H_model*Base%mod+(Model[i]-'A'+1)%mod)%mod;
for(i=1;i<=len1-len2+1;i++)
if(H_model==Get_Hash(i,i+len2-1))
result++,i+=len2-1;//不能重复!!!
return result;
}
int main()
{
Power[0]=1;
for(register int i=1;i<=1000;i++)
Power[i]=Power[i-1]*Base%mod;
while(scanf("%s",Main+1)&&Main[1]!='#')
{
scanf("%s",Model+1);
printf("%d\n",Count());
}
return 0;
}
At last:
puts("点个赞吧!");