文字列照合--BMアルゴリズム

私は最近インタビューの準備をしていましたが、BMアルゴリズムについて知る前に、文字列照合に関する質問を見ました(ルールの一部のアルゴリズムを深く研究しなかったのは非難されただけです)。

上手!BMアルゴリズムとは何かを紹介するだけで、Baidu百科事典の説明を見てみましょう。

コンピュータサイエンスボイヤー-ムーア文字列検索アルゴリズムは非常に効率的である文字列検索アルゴリズム1977年にボブボイヤーとJストローザームーアによって設計されました。このアルゴリズムは、検索された文字列ではなく、検索対象の文字列(キーワード)のみを前処理します。ボイヤームーアアルゴリズムの実行時間も検索された文字列のサイズに直線的に依存しますが、通常は他のアルゴリズムのごく一部にすぎません。検索された文字列の文字を1つずつ比較する必要はなく、その一部をスキップします。一般に、検索キーワードが長いほど、アルゴリズムは高速になります。その効率は、一致の試行が失敗するたびに、アルゴリズムがこの情報を使用して、一致しない場所をできるだけ多く排除できるという事実に由来します。

次に、BMアルゴリズムの詳細を以下に紹介します。もちろん、このブログでは他の記事を使用して要約を作成します。これは、BMアルゴリズムの理解に関する著者のメモでもあります。読者の役に立つことを願っています。あまりありません。つまり、トピックに直接移動してください。

アルゴリズムを理解するには、最初にアルゴリズムの原理とアイデアを知る必要があります。これは非常に重要なので、最初にBMアルゴリズムの原理へのエントリポイントを作成します。

接尾辞の比較(右から左への比較方法)に基づくBMアルゴリズム、およびBMアルゴリズムには、実際には2つの並列アルゴリズムが含まれています不正な文字ルール良好な接尾辞ルールです。

(BMアルゴリズムのアイデアについてのブログを読むことをすべての人に推奨します:文字列照合BMアルゴリズム学習

まず、2つのアルゴリズムルールを明確にする必要があります。

1.悪いキャラクタールール:

バックシフト番号=不良文字の位置-パターン文字列内の不良文字の最後の出現位置

 「不良文字」がパターン文字列に含まれていない場合、最後の出現位置は-1です。例として次の2つの文字列を取り上げます

「G」と「H」が一致しないため、「G」は「不良文字」と呼ばれ、パターン文字列(パターン文字列はFGH)の2番目の位置(0からの番号付け)に表示され、パターン文字列。最後に出現した位置は1だったので、2-1 = 1桁後ろにシフトします。

 2.適切なサフィックスルール 

 バックシフト番号=適切な接尾辞の位置-パターン文字列の最後の出現位置

たとえば、パターン文字列「ABCDEFABCD」の最後の「AB」が「適切なサフィックス」である場合です。次に、その位置は6(0から数えて最後の「B」の値を取る)であり、パターン文字列の最後の出現位置は1(最初の「B」の位置)であるため、6-1 =シフトされます。 5ビットの場合、前の「AB」は次の「AB」の位置に移動します。

別の例を挙げると、パターン文字列「ABCDEFGH」の「EF」が適切な接尾辞である場合、「EF」の位置は5であり、最後に出現する位置は-1です(つまり、表示されませんでした)。 、したがって、5-(-1)= 6桁だけシフトバックされます。つまり、文字列全体が「F」の最後の桁に移動されます。

      このルールについて注意すべき点が3つあります。

  1. 「適切な接尾辞」の位置は、最後の文字に基づいています。「ABCDEF」の「EF」が適切な接尾辞であると仮定すると、その位置は「F」(0から数えて)の影響を受けます。
  2. 「適切な接尾辞」がパターン文字列に1回だけ出現する場合、その最後の出現位置は-1です。たとえば、「EF」が「ABCDEF」に1回だけ出現する場合、最後の出現位置は-1です(つまり、出現しませんでした)。
  3. 「適切な接尾辞」が複数ある場合は、最も長い「適切な接尾辞」を選択し、最後に出現する位置を先頭にする必要があります。たとえば、「BABCDAB」の「良い接尾辞」が「DAB」、「AB」、「B」の場合、この時点で最後に出現する「良い接尾辞」は何ですか。答えは、この時点で使用されている適切な接尾辞は「B」であり、最後に表示される位置は頭、つまり0番目の位置であり、他の適切な接尾辞の最後の位置は頭にありません。

今、そのような要求があります:文字列が次のような別の文字列に表示されるかどうかを知りたい

String originText = "ABCDEFGHHH"
String moduleText = "FGGH";

moduleTextがoriginTextに表示されるかどうかを判別します。表示される場合は、表示される位置のインデックスを返し、表示されない場合は-1を返します。(もちろん、ここでは文字列オブジェクトAPIのシナリオをとりあえず放棄し、アルゴリズムから始めます!!!)。同時に、問題についても説明する必要があります。一致した文字列としてのmoduleText(パターン文字列とも呼ばれます)と、検索された文字列としてのoriginText(メイン文字列とも呼ばれます)です。

1.まず、メインストリングをパターンストリングのヘッドに合わせ、テールから比較を開始します。このアイデアは非常に効率的です。末尾の文字が一致しない場合、最初の10文字(全体として)が1回の比較で探している結果ではないことが確実にわかるためです。「C」が「H」と一致しないことがわかります。このとき、「C」は「悪い文字」と呼ばれます。このとき、悪い文字のルールは3、良い接尾辞のルールは-1、大きい方がバックシフト番号として選択されます。ここでは選択肢3

2.最後から比較すると、「F」と「H」が一致していないことがわかり、「F」は「悪いキャラクター」です。

アナロジー、そして最終的に得る

実装コードは次のとおりです

package www.supermaster.cn.text;

/**
 * 坏字符规则: 后移位数 = 坏字符的位置 - 模式串中的坏字符上一次出现位置
 * 
 * 好后缀规则:后移位数 = 好后缀的位置 - 模式串中的上一次出现位置
 * 
 */
public class BMTest
{

	public static void main(String[] args)
	{
		// 主串
		String originText = "ABCDEFGHHFGHH";
		// 模式串
		String moduleText = "FGH";
		// 坏字符规则表
		//	        int[] badCharacterArray = badCharacter(originString,moduleString);

		System.out.println("主串:" + originText);
		System.out.println("模式串:" + moduleText);

		int index = bmMatch(originText, moduleText);
		System.out.println("匹配的下标:" + index);
	}

	/**
	 * @Description:[BM匹配字符串]
	 * @Method: bmMatch
	 * @param originText
	 *            主串
	 * @param moduleText
	 *            模式串
	 * @return 若匹配成功,返回下标,否则返回-1
	 */
	public static int bmMatch(String originText, String moduleText)
	{
		// 主串
		if (originText == null || originText.length() <= 0)
		{
			return -1;
		}
		// 模式串
		if (moduleText == null || moduleText.length() <= 0)
		{
			return -1;
		}

		//如果模式串的长度大于主串的长度,那么一定不匹配
		if (moduleText.length() > originText.length())
		{
			return -1;
		}

		int moduleSuffix = moduleText.length() - 1;// 模式串最大长度值
		int moduleIndex = moduleSuffix; // 初始化模式串起始Index
		int originIndex = moduleSuffix; // 初始化主串初始化Index
		//
		for (int index = originIndex; originIndex < originText.length() && moduleIndex >= 0;)
		{
			char och = originText.charAt(originIndex); // 主串某个位置的Char
			char mch = moduleText.charAt(moduleIndex); // 模式串某个位置的Char
			//
			if (och == mch)
			{
				originIndex--;
				moduleIndex--;
			}
			else
			{
				// 坏字符规则
				int badMove = badCharacterRule(moduleText, och, moduleIndex);
				// 好字符规则
				int goodMove = goodCharacterRule(moduleText, moduleIndex);

				// 主串位置不动,模式串向右移动
				originIndex = index + Math.max(badMove, goodMove);
				moduleIndex = moduleSuffix;
				// index就是中间变量
				index = originIndex;
			}
		}

		if (moduleIndex < 0)
		{
			// 多减了一次
			return originIndex + 1;
		}

		return -1;
	}

	/**
	 * @Description:[利用好后缀规则计算移动位数]
	 * @Method: goodCharacterRule
	 * @param moduleText
	 * @param charSuffix
	 * @return
	 */
	private static int goodCharacterRule(String moduleText, int charSuffix)
	{
		int result = -1;
		// 模式串长度
		int moduleMax = moduleText.length();

		// 好字符数
		int charSize = moduleMax - 1 - charSuffix;

		for (; charSize > 0; charSize--)
		{
			String startText = moduleText.substring(0, charSize);
			String endText = moduleText.substring(moduleMax - charSize, moduleMax);
			if (startText.equals(endText))
			{
				result = moduleMax - charSize;
			}
		}

		return result;
	}

	/**
	 * @Description:[利用坏字符规则计算移动位数]
	 * @Method: badCharacterRule
	 * @param moduleText
	 * @param badChar
	 * @param charSuffix
	 * @return
	 */
	private static int badCharacterRule(String moduleText, char badChar, int charSuffix)
	{
		return charSuffix - moduleText.lastIndexOf(badChar, charSuffix);
	}

}

この記事は主にインタビューの状況を対象としており、コードがメインの表示と表示であり、フォローアップは今後も改善されていきます。読者から良い提案があれば、一緒に進歩するように私たちを励ますメッセージを残してください!

継続的改善..............

-------------------------------------------------- --------------------------------------作成
者:世界のコーディング
ソース:CSDN
オリジナル:HTTPS:/ /blog.csdn.net/dgxin_605/article/details/92360040
著作権表示:この記事はブロガーの元の記事です。転載する場合は、ブログ投稿へのリンクを添付してください。

 

おすすめ

転載: blog.csdn.net/dgxin_605/article/details/92360040