문자열 주제 KMP, 다음 배열 문제, 해시, Manacher, 무차별 대입 일치, 눈금자 가져 오기, AC 자동 장치, Kuangbin 질문 시트

현재 기본 문자열 문제의 경우 기존 솔루션 KMP, 다음 배열 문제, 해시, Manacher, 무차별 대입 일치, 눈금자 및 사전 트리, 접미사 배열, ac 자동 및 접미사 자동,
kmp
하위 문자열이 상위 문자열에 있습니다. 문자열 매칭 문제를 해결하기위한 발생 횟수

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;
}

별도로 다음 배열 찾기 : 링 유형의 반복 발생 문제 및 정의에 대한 일부 판단 해결

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];
        }
	}
}

해시 : 숫자를 사용하여 문자열을 저장하고 다른 문자열로 숫자를 판단하며 주로 문자열 매칭 문제를 해결하는 방법입니다.

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];
}//每个位置上从前向后的哈希值

말이 끄는 카트 보드 : 현의 회문 길이 문제 해결

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中最长回文串
}

폭력적 일치 : 즉, 부모 문자열의 각 문자 위치를 판단하기 위해 일치하면 다음 문자가 일치하는지 여부를 판단하고 그렇지 않으면 다음 위치로 점프합니다.

최근에 ac automata의 내용에 대해 조금 배웠는데, 보드 뒷면에 추가 질문을하시면 자세히 적어 보겠습니다. 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]];
        }
    }
}

가장 긴 회문 문자열
일반적으로 가장 긴 회문은 말이 끄는 수레를 사용하며 2 차원 dp로 전송할 수도 있습니다. 문자열의 경우 dp [i] [j]를 사용하여 i 번째 문자부터 문자열의 j 자 문자까지 가장 긴 회문 하위 시퀀스를 나타냅니다.
s [i] == s [j]이면 전송할 수 있습니다. 회문 하위 시퀀스의 양쪽으로
s [i]! = s [j] 이면 모든 dp [i] [j] = d [i + 1] [j-1] +2
를 양쪽으로 전송할 수 없습니다. 회문 하위 시퀀스, 따라서 dp [i] [j] = max (d [i + 1] [j], dp [i] [j-1])


가장 긴 회문을 형성하기 위해 두 줄의 차이에 대해

#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;
}

추천

출처blog.csdn.net/qq_45891413/article/details/109123713