暗号

链接:https://ac.nowcoder.com/acm/contest/12478/B
来源:牛客网
题目描述
小源很快就是破解了小凡的暗号,于是小凡想了一个办法,那就是将暗号进行hashhashhash处理,这下小源就没法识破了。
总所周知,hashhashhash算法是会产生冲突的,即两个串的hashhashhash值可能相同。现在给你一个hashhashhash函数,以及相关参数,再给一个字符串sss,小凡想知道所有长度为nnn的串里面,有几个串与sss串的hashhashhash值相同。

小凡采用的hashhashhash方法如下:
long long gethash(string s)
{
long long hashsum = 0;
for(int i=0; i<s.size(); i++)
hashsum = (hashsum*base+s[i]-‘a’)%p;
return hashsum;
}

输入描述:
第一行三个整数base,pbase,pbase,p(1≤base,p≤105)(1\le base,p\le10^5)(1≤base,p≤105)表示hashhashhash函数的参数,nnn(1≤n≤20)(1\le n\le 20)(1≤n≤20)表示要求的长度。
第二行一个字符串sss,用Len(s)Len(s)Len(s)表示sss的长度,保证1≤Len(s)≤201\le Len(s)\le201≤Len(s)≤20。
输出描述:
输出与sss串hashhashhash值相同的字符串个数(如果Len(s)=nLen(s)= nLen(s)=n的话,也包括它本身)。
由于答案可能会很大,请对109+710^9+7109+7取模。
示例1
输入
1 13 1
a
输出
2
示例2
输入
10 97 5
abb
输出
122495

又一道动态规划。
题目给了你一种计算hash值的方法,你输入一串字符串(s)后就会得到对应的hash值,并且问你指定长度的字符串中有几个和字符串s的hash值相同。
思路:dp[ i ][ j ]表示长度为 i 的字符串对应 hash 值为 j 的个数有几个。根据所给的函数可以发现长度为 i - 1的字符串加上一个字母后所得的hash值为
hash = ( j * base + k ) % p,此时的hash值就可以存放到dp[ i ][ hash ]中,
即动态方程为dp[ i ][ hash ] = ( dp[ i ][ hash ] + dp[ i-1 ][ j ]) % mod。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1000000007;
int dp[22][100005];
LL base, p, n, hs;
string s;
LL gethash(string s)
{
    
    
	LL hashsum = 0;
	for (int i = 0; i<s.size(); i++)
		hashsum = (hashsum*base + s[i] - 'a') % p;
	return hashsum;
}
int main() {
    
    
	cin >> base >> p >> n;
	cin >> s;
	memset(dp, 0, sizeof(dp));
	hs = gethash(s);
	for (int i = 0; i < 26; i++)
		dp[1][i%p]++;
	for (int i = 2; i <= n; i++) {
    
    
		for (int j = 0; j < p; j++) {
    
    
            if(dp[i-1][j]==0) continue;
			for (int k = 0; k < 26; k++) {
    
    
				LL newHs = (j*base + k) % p;//hash值为j时再增加一位字母[0-25]得到新的hash值
				dp[i][newHs] = (dp[i][newHs] + dp[i - 1][j]) % mod;
			}
		}
	}
	cout << dp[n][hs] << '\n';
	return 0;
}

诶~

猜你喜欢

转载自blog.csdn.net/m0_54069398/article/details/115048512
今日推荐