文字列の件名KMP、次の配列の問題、ハッシュ、マナチャー、ブルートフォースマッチング、定規の取得、acオートマトン、クアンビン質問シート

現在、基本的な文字列の問題、既存のソリューションKMP、次の配列の問題、ハッシュ、マナチャー、ブルートフォースマッチング、ルーラーと辞書ツリー、接尾辞配列、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])


最長の回文を形成する2つの弦の違いについては、

#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