El número de apariciones de la cadena B en A (sin plantilla módulo + módulo)

Enlace de tema

Dada una cadena A y una cadena B, calcule el número de apariciones de B en A.

B que aparece en diferentes posiciones en A puede superponerse.

Aporte

Hay dos líneas de entrada, la cadena A y la cadena B.

Producción

Genere un número entero que represente el número de apariciones de B en A.

Entrada de muestra

zyzyzyz
zyz

Salida de muestra
3

PISTA

1≤A, la longitud de B≤10e6, A y B solo contienen letras mayúsculas y minúsculas.

Análisis:
problema de cadenas: generalmente hay dos métodos de hash y Kmp

String Hash (hash):
el problema buscado: encuentre la posición o el número de veces que la cadena B aparece en la cadena A.

Pensamiento violento

	枚举字符串A中个所有位置,非常浪费时间
	例如字符串A为aaaaaaaaaaab     字符串B为aaaab

Pensamiento hash

例如字符串A为aaaaaaaaaaab     字符串B为aaaab
字符串B长度=5,求出字符串B的哈希值,并且利用前缀和思想求字符A的哈希值
然后利用前缀和思想可知任意一段长度的哈希值

El siguiente paso es encontrar la posición donde el valor hash de la cadena A tiene una longitud de 5 y es igual al valor hash de la cadena B. Por supuesto, también puede encontrar el número

Utilice prefijos e ideas para encontrar el valor hash del carácter A. Ideas específicas:

假设字符A为ACDA,字符串B为CD,这里在假定A=1,C=3,D=4
这里只是简化下面的叙话,写代码过程中无需这么写
首先,引入一个质数B,不要太大也不要太小
接着  定义H[0]=1,长度为i的哈希值定义为H[i]
H(1)=1
H(2)=1*B+3
H(3)=1*B^2+3*B+4
H(4)=1*B^3+3*B^2+4*B+1

Obviamente, H [k + 1] = H (k) * B + c [k + 1]Inserte la descripción de la imagen aquí

Aquí c es la cuerda, m es la longitud de la cuerda

同理可得B的哈希值为s=3*B+4
我们可以发现H(3)-H(2)*(B^2)==3*B+4
很明显,最后乘以B的几次方是根据字符串B的长度而定的

La exactitud del hash de la cadena (no lo entiendo muy bien, pero estos son los teoremas de los predecesores)

字符串Hash对于任意不同的字符串所产生的哈希值必然是互不相同的吗
显然不是的
但如果我们的哈希函数所生成的哈希值是随机分布的话,不同的字符串哈希值相等的
概率是很低的,因此我们常常认为竞赛中的题目不会出现字符串相等的情况,实际上
根据生日悖论,对于[0,n)内均匀分布的哈希函数,出现不同字符串哈希值相等
的期望是O(sqrt(n)),这在选择哈希函数时可以作为一个效率和正确性参考。

Aquí para explicar, la función hash aquí es así
Inserte la descripción de la imagen aquí

De hecho, la importancia de modular no es explotar los datos, pero también es correcto no modular esta pregunta, porque la computadora también tiene ciertas reglas de procesamiento para datos explotados, y no devuelve un valor al azar, por lo que podemos determinar que es para los dos explotados. Para un número diferente, el valor devuelto por la computadora no es el mismo. En esta pregunta, solo consideramos que los valores hash no son iguales, independientemente de si es positivo o negativo.

Pero si necesita usar el valor hash como subíndice en algunas preguntas, debe tomar el módulo

Para mejorar la corrección de Hash

可以采用“双哈希”来降低不同字符串出现相同哈希值的概率,即取不同的模数,把
不同模数算出的哈希值都记下来,只有几个哈希值都一样,我们才判定字符串匹配。
通常用双哈希就可以就可以将冲突降到最低,如果分别取h=10e9+7和10e9+9,就
几乎不可能发生冲突,因为他们是一对“孪生质数”。当然为了考虑下标,我们可以
考虑取10e6左右的质数,比如999979。

El código de la pregunta: (sin módulo)
Inserte la descripción de la imagen aquí

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 1000010
#define B 31
using namespace std;
typedef long long ll;
char a[maxn],b[maxn];
ll sum[maxn];//用来存放前i位哈希值 
ll power[maxn];
void init()//存储B^n(n=1,2,3,4,5,6...) 
{
	power[0]=1;
	for(int i=1;i<=1000000;i++)
		power[i]=power[i-1]*B;//爆了按溢出处理 
}
int main()
{
	init();//预处理 
	while(~scanf("%s",a+1))//下标从1开始 //a[0]='\0'; 
	{
		int i,j;
		scanf("%s",b+1);
		int la=strlen(a+1);//长度未变 
		int lb=strlen(b+1); 
		if(la<lb)
			printf("0\n");
		else
		{
			sum[0]=0;
			for(i=1;i<=la;i++)
				sum[i]=sum[i-1]*B+(a[i]-'A'+1);//可减A也可以不减
			
			ll s=0;//存储匹配串哈希值 
		
			for(i=1;i<=lb;i++)
				s=s*B+(b[i]-'A'+1);
			
			int ans=0;//记符合几串
			for(i=0;i<=la-lb;i++)
			{
				if(s==sum[i+lb]-sum[i]*power[lb])
					ans++;
			}
			printf("%d\n",ans); 
		}
	}
	return 0;
} 

Código de módulo (hash único)
Inserte la descripción de la imagen aquí

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 1000010
#define B 31
using namespace std;
typedef long long ll;
char a[maxn],b[maxn];
ll sum[maxn];//用来存放前i位哈希值 
ll power[maxn];
ll mod=1e9+7;
void init()//存储B^n(n=1,2,3,4,5,6...) 
{
	power[0]=1;
	for(int i=1;i<=1000000;i++)
		power[i]=(power[i-1]*B)%mod;//爆了按溢出处理 	
}
int main()
{
	init();//预处理 
	while(~scanf("%s",a+1))//下标从1开始 //a[0]='\0'; 
	{
		int i,j;
		scanf("%s",b+1);
		int la=strlen(a+1);//长度未变 
		int lb=strlen(b+1); 
		if(la<lb)
			printf("0\n");
		else
		{
			sum[0]=0;
			for(i=1;i<=la;i++)
				sum[i]=(sum[i-1]*B+a[i])%mod;
			
			ll s=0;//存储匹配串哈希值 
		
			for(i=1;i<=lb;i++)
				s=(s*B+b[i])%mod;
			
			int ans=0;//记符合几串
			for(i=0;i<=la-lb;i++)
			{
				if((s==((sum[i+lb]-sum[i]*power[lb])%mod+mod)%mod))
					ans++;
			}
			printf("%d\n",ans); 
		}
	}
	return 0;
} 

Supongo que te gusta

Origin blog.csdn.net/Helinshan/article/details/109533923
Recomendado
Clasificación