Asunto de cadena KMP, siguiente problema de matriz, hash, Manacher, coincidencia de fuerza bruta, toma de reglas, autómatas de CA, hoja de preguntas de kuangbin

En la actualidad, para problemas básicos de cadenas, las soluciones existentes KMP, siguiente problema de matriz, hash, Manacher, coincidencia de fuerza bruta, árbol de reglas y diccionario, para matrices de sufijos, autómatas ac y autómatas de sufijo, la subcadena
kmp
está en la cadena principal. número de ocurrencias para resolver el problema de la correspondencia de cadenas

char a[maxn],b[maxn];
ll lena,lenb;
int next1[maxn];
void getnext(){
    
    
	next1[0]=-1;
	int i=0,j=-1;
	while(i<lena){
    
    //子串
		if(j==-1||a[i]==a[j]){
    
    //子串
			i++;j++;
			if(a[i]==a[j]) next1[i]=next1[j];
			else next1[i]=j;
		}
		else{
    
    
			j=next1[j];
		}
	}
}

int KMP(){
    
    
	int i=0,j=0,ans=0;
	while(i<lena&&j<lenb){
    
    //子串 母串
		if(i==-1||a[i]==b[j]){
    
    
			i++;j++;
		}
		else i=next1[i];
		if(i==lena){
    
    
			ans++;//出现次数....
			i=next1[i];
		}
	}
	return ans;
}

Buscar por separado la siguiente matriz: resolver el problema de las ocurrencias repetidas del tipo de anillo y algunos juicios sobre la definición

int next1[maxn];
void getnext()
{
    
    
	next1[0]=-1;
	int i=0,j=-1;
	while(i<lena)
	{
    
    
		if(j==-1||a[i]==a[j])
		{
    
    
		    i++;j++;
			if(a[i]==a[j])next1[i]=next1[j];
			else next1[i]=j;
		}
		else
        {
    
    
            j=next1[j];
        }
	}
}

Hash: use un número para almacenar una cadena y juzgue el número con otras cadenas. Es principalmente un método para resolver el problema de la coincidencia de cadenas

ll hash1[maxn];
int lena,lenb;
for(int i=0;i<lena;i++){
    
    
	sum=sum*base+(int)a[i];
}//子串的哈希值
hash1[0]=0;
for(int i=1;i<=lenb;i++){
    
    
	hash1[i]=hash1[i-1]*base+b[i-1];
}//每个位置上从前向后的哈希值

Tablero de carro tirado por caballos: resuelve el problema de la longitud del palíndromo en la cuerda

string Manacher(string s1){
    
    
	string s="$#";//占空位0插入符号1
	for(int i=0;i<s1.size();i++)
		s+=s1[i],s+='#';
	vector<int>p(s.size(),0);//p储存回文串长度
	int id=0,mx=0,maxpoint=0,maxlen=0;//mx对应最右边 id为对应中点 maxpoint最长回文对应中点  maxlen最长长度
	for(int i=1;i<s.size();i++){
    
    
		p[i]=mx>i+p[i]?min(mx-i,p[2*id-i]):1;
		while(s[i+p[i]]==s[i-p[i]]) ++p[i];
		if(i+p[i]>mx) id=i,mx=i+p[i];//更新右端和中间,节间更新左边端点
		if(p[i]>maxlen) maxlen=p[i],maxpoint=i;//更新最大长度和对应中心点
	}
	return s1.substr((maxpoint-maxlen)/2,maxlen-1);//s1中最长回文串
}

Coincidencia violenta: es decir, para juzgar la posición de cada carácter en la cadena principal, si coincide, juzgue si el siguiente carácter coincide, de lo contrario, salte a la siguiente posición

Recientemente aprendí un poco sobre el contenido de los autómatas ac. Lo escribiré en detalle cuando ponga una pregunta complementaria en la parte posterior de la pizarra. Recuerde que esta es la pregunta escrita por el código ascall.

int trie[maxn][4], fail[maxn], tail[maxn];
int  n, m, pos;
char s[15];
map<char, int>idx;
void insert(){
    
    
    int ls=strlen(s),root=0;
    for(int i=0;i<ls;i++){
    
    
        int x=idx[s[i]];
        if(trie[root][x]==0)
            trie[root][x]=++pos;
        root=trie[root][x];
    }
    tail[root]=1;
}

void getfail(){
    
    
    queue<int>qu;
    for(int i=0;i<4;i++){
    
    
        if(trie[0][i]){
    
    
            fail[trie[0][i]]=0;
            qu.push(trie[0][i]);
        }
    }
    while(!qu.empty()){
    
    
        int now=qu.front();
        qu.pop();
        for(int i=0;i<4;i++){
    
    
            if(trie[now][i]){
    
    
                fail[trie[now][i]]=trie[fail[now]][i];
                qu.push(trie[now][i]);
            }
            else trie[now][i]=trie[fail[now]][i];
            tail[trie[now][i]]|=tail[trie[fail[now]][i]];
        }
    }
}

La cuerda del palíndromo más larga
En términos generales, el palíndromo más largo utiliza un carro tirado por caballos y también puede ser transferido por dp bidimensional. Para una cadena, usamos dp [i] [j] para representar la subsecuencia de palíndromo más larga desde el carácter i-ésimo hasta el carácter j de la cadena.
Si s [i] == s [j] entonces se puede transferir A ambos lados de la subsecuencia palíndromo, todos los dp [i] [j] = d [i + 1] [j-1] +2

si s [i]! = S [j] no se pueden transferir a ambos lados del subsecuencia palíndromo al mismo tiempo, Entonces dp [i] [j] = max (d [i + 1] [j], dp [i] [j-1])


Para que la diferencia entre dos cuerdas forme el palíndromo más largo, hay

#include<bits/stdc++.h>
using namespace std;
char a[55],b[55];
int f[55][55][55][55];
int main(){
    
    
    int t;
    cin>>t;
    while(t--){
    
    
        scanf("%s",a+1);
        scanf("%s",b+1);
        int m,n;
        n=strlen(a+1);
        m=strlen(b+1);
        int ans=0;      
        for(int len1=0;len1<=n;len1++)
            for(int len2=0;len2<=m;len2++)
                for(int i=1;i+len1-1<=n;i++)
                    for(int j=1;j+len2-1<=m;j++){
    
    
                        int r=i+len1-1;
                        int l=j+len2-1;
                        if(len1+len2<=1) f[i][r][j][l]=1;
                        else{
    
    
                            f[i][r][j][l]=0;
                            if(len1>1) f[i][r][j][l]|=((f[i+1][r-1][j][l])&&(a[i]==a[r]));
                            if(len1&&len2) f[i][r][j][l]|=(f[i+1][r][j][l-1]&&(a[i]==b[l]));
                            if(len1&&len2) f[i][r][j][l]|=(f[i][r-1][j+1][l]&&(a[r]==b[j]));
                            if(len2>1) f[i][r][j][l]|=(f[i][r][j+1][l-1]&&(b[j]==b[l]));
                        }
                        if(f[i][r][j][l]){
    
    
                            ans=max(ans,len1+len2);
                        }
                    }
        cout<<ans<<endl;
    }
    system("pause");
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_45891413/article/details/109123713
Recomendado
Clasificación