codeforces 149E Z-box / Z-algoritmo de coincidencia de cadenas

El significado de los problemas

Para darle una cadena de texto, la coincidencia de cadenas n abajo, preguntas cómo muchos de los que se pueda hacer de p s [i ~ j] + s [l ~ r] en virtud, puede degenerar en un párrafo (j = l);

pensamiento

Z-cuadro título de la plantilla, matriz pos es el alma

Fueron tratados de p + '#' + s (Getz void) () P + '#' + S (void Getz ()) z-array (mayúsculas orden minúsculas inversa),

POS [i] registra la longitud de la derecho mínimo límite de la mitad delantera del campo i, es decir, Getz () en pos [z [i] - len ] = min (pos [z [i] - len], i + z [i] - 1 - LEN); enumeración tomada min: ... for (int len = I - 1; I> = 1; i--) POS [I] = min (POS [. I + 1] - 1, POS [I] ); // [ah ah ah alma así tratado está fuera de los límites del mínimo]

Bueno Después pos ok, Getz (), para cada bit (i> len) en P, se determina si un medio después de hechizo --Si (pos [len - z [i]] <= len + LEN - i - Z [i] + 1); // pos [len - z [i]] es una mitad delantera del límite derecho se determina si el sub-segmento actual es inferior a igual al margen izquierdo como el segundo medio.

wa Medio varias razones para el cabello deben ser POS [0] = 0  siempre igual a inf y no actualizó pos [0] me dan todo el tontas amigos

ACcode

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;
const int MaxN = 1e5 + 1115;
const int inf = 0x3f3f3f3f;

int n,cnt,len,LEN;
char s[MaxN],S[MaxN],p[MaxN],P[MaxN];
int pos[MaxN],z[MaxN];

void getz(){
	int l = 0,r = 0;
	z[0] = 0;
	for(int i = 1;i <= LEN + len; i++){
		if(i > r){
			int n = 0;
			while(p[n] == p[i + n]) n++;
			if(n){
				l = i;
				r = i + n - 1;
			}
			z[i] = n;
		}
		else{
			if(z[i - l] < r - i + 1) z[i] = z[i - l];
			else{
				int n = 1;
				while(p[r - i + n] == p[r + n]) n++;
				r = r + n - 1;
				l = i;
				z[i] = r - l + 1;
			}
		}
		if(i > len) pos[z[i]] = min(pos[z[i]],i + z[i] - 1 - len);
		//pos[i]记录长度为i的字段的最小位置 from 1
	}
	for(int i = len - 1;i >= 1; i--) pos[i] = min(pos[i + 1] - 1,pos[i]);
}

void getZ(){
	int l = 0,r = 0;
	z[0] = 0;
	for(int i = 1;i <= LEN + len; i++){
		if(i > r){
			int n = 0;
			while(P[n] == P[i + n]) n++;
			if(n){
				l = i;
				r = i + n - 1;
			}
			z[i] = n;
		}
		else{
			if(z[i - l] < r - i + 1) z[i] = z[i - l];
			else{
				int n = 1;
				while(P[r - i + n] == P[r + n]) n++;
				r = r + n - 1;
				l = i;
				z[i] = r - i + 1;
			}
		}
		
		if(i > len){//i是倒数第i个
			if(pos[len - z[i]] <= LEN + len - i - z[i] + 1){
				//pos[len - z[i]]:前半段右边界min
				cnt++;//存在多种拆分答案
				break;
			}
		}
	}
}

int main()
{
	scanf("%s",s);
	scanf("%d",&n);
	LEN = strlen(s);
	for(int i = 0;i < LEN; i++) S[i] = s[LEN - i - 1];
	while(n--){
		for(int i = 1;i < MaxN; i++) pos[i] = inf;
		scanf("%s",p);
		len = strlen(p);
		if(len == 1) continue;
		p[len] = '#';
		for(int i = 0;i < LEN; i++) p[len + i + 1] = s[i];
		getz();
		for(int i = 0;i < len; i++) P[i] = p[len - i - 1];
		P[len] = '#';
		for(int i = 0;i < LEN; i++) P[len + i + 1] = S[i];
		getZ();
	}
	printf("%d\n",cnt);
}

 

Publicado 31 artículos originales · ganado elogios 5 · Vistas 1364

Supongo que te gusta

Origin blog.csdn.net/qq_43685900/article/details/103163058
Recomendado
Clasificación