文字列マッチングの基礎(中):機能テキストエディタを見つける方法
ワードは、BMアルゴリズムを統一し、他に置き換え内の単語を使用することができています
BMアルゴリズムの核となるアイデア
メインストリングパターン文字列のマッチング処理を、メインストリングcがパターン文字列にはないので、そうするとき後方にスライディングからパターン、限りがオーバーラップパターン列Cであり、そして、確かにパターン文字列と一致しないように使い捨てであることができますいくつかのスライドバック、パターン文字列は、バックcに移動させ、
BMアルゴリズム理論解析
BMアルゴリズムは、2つの部分からなる善と悪の文字ルールサフィックスルールであります
1.悪い文字のルール
パターン文字列の降順添え字、逆マッチング
前方、後方、この文字は、任意の既知の不正な文字(メイン文字列)と一致しませんでしたときに我々は一致する文字列を見つけることができないパターンマッチング文字列の末尾から、我々は、パターン文字列cで不正な文字を見つけます(パターン文字列のみ3ので)、その後、パターン文字列cの背面にスライドし、文字列の文字モードの端から開始し、パターン文字列は、この文字を持っていないことが判明し、今回は直接パターン文字列はバック3点の位置をスライドさせることができます比較します
この文字は、再整合、文字列パターンの最後から2つのパターン文字列は、後ろにスライドので、2つの垂直に整列していること、と悪い時間ではなく、3枚のスライド帰ってきました
悪い文字がパターン文字列内に存在する場合、ミスマッチ、SIとしてラベルの文字のパターン文字列に対応する次の不正な文字は、パターン文字列で、この不正な文字は、その、XIとしてラベル付けするときに発生存在しない場合は、XI = -1は、ビットの数は、バックパターン文字列SIを移動している - XI(添字で添字文字列パターン)
abcacabdc
アブド
文字が悪いです。この時点で、dが悪いパターンは文字インデックスに対応する文字の文字列、D = SI = 2、= XI = 0であります
多くの不正な文字がパターン文字列に表示された場合は、計算XI時間は1つの最も後方を選択します
単に悪い文字のルールを使用し十分ではありません、我々はまた、「良いサフィックスルール」を使用する必要があります
2.グッドサフィックスルール
モードは、文字列パターン文字列とは、二つの主な文字は、終わりから3番目悪い文字を一致された文字列の下側の位置にスライドされたとき
abcacabcbcbacabc
abbcabc
悪いキャラクター、BCは良い接尾辞です
私たちは、あなたが良い取引サフィックスルールを使用することができ、スライド桁の文字列のモードを計算するために、悪い文字規則を使用することができます
サフィックスは{U}で表さ行うために呼び出さ良いマッチ接尾辞BCを、持っていることが見つかった場合、パターン文字列を見て紀元前取る別で子供を{U}は文字列U {マッチする*
}、文字列スライディングモードUは、{ことサブストリング*
}位置でメインストリング{U}を整列し、他のISは、{U}が直接パターン文字列に、サブストリングに等しくない場合、{U}のように、メインストリームの後部にスライドバック摺動いずれかは、全く一致メインストリング{U}前の場合に認められなかったが、これはおそらく過大スリップあるれます
だけでなく、必要サフィックス文字列モードについて楽観我々はので、別の試合のストリングがある場合、我々は試合をサブストリング接頭辞を持つパターン文字列があるかどうか、良い接尾サブストリングを検討する必要があります
これは、文字列の接尾サブストリングと呼ばれるS、最後の文字は、次のようなabcの接尾サブC、BCを含む、Sサブストリングと整列しています。いわゆる接頭サブストリング、sは、このようなABC接頭サブストリングとして、開始文字列のサブと整列し、ABを持っています。我々は良いサフィックスから部分サフィックス最長プレフィックス文字列パターンマッチングストリングを見つけるために並べ替えられ、{V}と仮定します
どのように良いのか悪いのルール文字サフィックスルールを選択するには?
計算中央値は善と悪の文字が次のスライドをサフィックスした後、モード・ビットをスライドするように2つの数字、次の文字列の最大値を取ります
BMアルゴリズムコードの実装
不正な文字がパターン文字列に表示されるのはどのよう場所を見つけるには?
各文字列パターンは、あなたはすぐに、文字列の文字セットがあまりされていないと仮定し、不正な文字がハッシュテーブルの上に、位置モードで文字列をマーク見つけ、そしてすべてのことができ、ハッシュテーブルに保存され、そのインデックスにあってもよいです文字長が1バイト、配列256、配列添字文字の値に対応するASCIIコードのサイズとパターン文字列に表示される各文字の記録位置、パターン文字列に現れる配列に格納された文字の位置であります
パターン文字列:アブダ
0 1 2 3 BC:-1 -1 ...... 3 1 -1 -1 2 ......
0 1 ...... 97 98 99 100 255 ......
ASCIIコード表:97
B 98
C 99
D 100 ......
Bは、mはハッシュテーブルBC、パターンの長さ概略文字列であります
private static final int SIZE = 256;//全局变量或成员变量
private void generateBC(char[] b ,int m ,int[] bc){
for(int i = 0 ; i < SIZE ; ++i){
bc[i] = -1; //初始化bc
}
for(int i = 0 ; i < m ; ++i){
int ascii = (int)b[i];//计算b[i]的ASCII值
bc[ascii] = i ;
}
}
悪い文字原則の最初のケースにかかわらず、モバイル桁のSI-XIの計算だけは否定表示されることがあります
public int bm(char[] a , int n ,char[] b ,int m){
int[] bc = new int [SIZE]; //记录模式串中每个字符最后出现的位置
generateBC(b,m,bc); //构建坏字符哈希表
int i = 0; //i表示主串与模式串对齐的第一个字符
while( i <= n - m){
int j ;
for (j = m - 1 ; j >= 0 ; --j){ //模式串从后往前匹配
if(a[i+j] != b[j]) break; //坏字符对应模式串中的下标是j
}
if(j < 0){
return i; //匹配成功,返回主串与模式串第一个匹配的字符的位置
}
//这里等同于将模式串往后滑动 j - bc[(int)a[i+j]]位
i = i + (j - bc[(int)a[i+j]]);
}
return -1;
}
良好な接尾辞は、それ自体が別の位置に対応する、実際のマッチングパターン列及びメインストリングの前に、したがって、前処理モードによってストリングをサブストリングパターン文字列の接尾辞であるサブストリング一致させることができます
それの異なったパターン文字列のサフィックスの部分文字列を表現する方法は?最後接尾文字サブストリングの位置は固定されているので、下付き文字m-1は、唯一のレコード長さが必要であり、長さは、我々のような、固有のサフィックスストリングを決定することができます
パターン文字列:cabcab
ストリングのサフィックス長
B 1
AB 2
タクシー3
bcab 4
abcab 5
最も重要な変数接尾辞配列の導入、添え字Kサフィックスアレイ、良好なサフィックス{U}サブ一致文字列{Uとパターン文字列に格納された配列値に対応する長インデックスサブストリングサフィックス*
内を}開始インデックス値
パターン文字列:cabcab
0 1 2 3 4 5
ストリングのサフィックスサフィックス長
B 1つのサフィックス[1] = 2
AB 2サフィックス[2] = 1
タクシー3接尾辞[3] = 0
bcab 4サフィックス[4] = -1
5サフィックス[5] = -1 abcab
接尾辞文字列サブの開始位置にそれを格納{U}一致をサブストリングは、接尾辞配列と文字のパターン文字列が複数ある場合は?あるストレージモード、インデックスの最大の部分文字列の開始位置に最も近い文字列の後に文字の開始位置
だけでなく、パターン文字列で、良い試合を持つ別の接尾辞を見つけるサブストリングが、また、最長の部分文字列サフィックスを見つけるための良い接尾辞接尾辞ストリングに一致するサブストリングパターン文字列のプレフィックスをソートし、我々はブール値を必要とします記録モードにプレフィックス文字列配列接尾文字列は、サブパターン文字列の接頭部ストリングと一致する場合
パターン文字列:cabcab
0 1 2 3 4 5
接尾語長接尾辞接頭辞ストリング
B 1接尾= 2接頭辞=偽
AB 2接尾= 1接頭辞=偽
タクシー3接尾= 0接頭辞=真
bcab 4接尾= -1接頭辞=偽
abcab 5接尾= -1接頭辞=偽
サブストリング0からI(iはM-1 0)と、パターン全体に添え字文字列、共通接尾辞が長さkのサブ場合、共通接尾サブストリングを検索し、接尾辞[K] = J(Jはインデックスを開始サブストリングサフィックス共通)パターン文字列をサブストリングの共通接尾辞であるJ = 0は、プレフィックスストリングである場合、接頭辞[k]は真=
//b表示模式串,m表示长度,suffix,prefix数组事先申请好了
private void generateGS(char[] b ,int m,int[] suffix ,boolean[] prefix){
for(int i = 0 ; i < m ; ++i){ //初始化
suffix[i] = -1;
prefix[i] = false;
}
for(int i = 0 ; i < m -1 ;++i){ //b[0,i]
int j = i ;
int k = 0;//公共后缀子串长度
while(j >= 0 && b [j] == b[m-1-k]){ //与b[ o ,m-1]求公共后缀子串
--j;
++k;
suffix[k] = j+1; //j+1表示公共后缀子串在b[0,i]中的起始下标
}
if( j == -1) prefix[k] = true ; //如果公共后缀子串也是模式串的前缀子串
}
}
文字列マッチング処理とメインモードの文字列では、一致する文字がどのように良いサフィックスルール、数字の計算モード文字列次のスライドによると、満たされていませんか?
接尾辞[K]!= -1(-1が存在しない試合をサブストリング表す)、その後、我々はパターン文字列に行けば良い接尾語の長さは、配列におけるそのサフィックスのサブストリングサフィックスの取得の良い一致を見つけ、kは想定されJ-サフィックスを移動した後[K] +1ビット(jは文字列パターンインデックスに対応する不良文字を示す)、[K] =サフィックス場合 - 1、良好な接尾文字列サブによるさらなる整合パターンが存在しないことを示し文字列の部分。次のルールに対処します:
接頭辞[K] = TRUE、長さkを示している場合、長さk = M -rのB [R、M-1](R jの+ M-1の2つの値)サブストリング良いサフィックスサフィックス後にrビットのパターン文字列をシフトすることができるサブストリングとサフィックス、プレフィックスマッチをサブストリング
2つのルールが全体のmビットのシフトパターン文字列の後に良い試合と接尾サブサフィックス部分文字列を見つけることができない場合
//a,b表示主串和模式串;n,m表示主串和模式串的长度
public int bm(char[] a ,int n , char[] b ,int m ){
int[] bc = new int[SIZE] ; //记录模式串中每个字符最后出现的位置
generateBC(b,m,bc); //构建坏字符哈希表
int[] suffix = new int [m];
boolean[] prefix = new boolean[m];
int i = 0; // j 表示主串与模式串匹配的第一个字符
while( i <= n - m){
int j;
for(j = m - 1;j >= 0 ; --j){ //模式串从后往前匹配
if(a[i+j] != b[j]) break; // 坏字符对应模式串中的下标是j
}
if(j < 0){
return i ; // 匹配成功,返回主串与模式串第一个匹配的字符的位置
}
int x = j - bc[(int) a[i+j]];
int y = 0;
if(j < m-1){ //如果有好后缀的话
y = moveByGS(j ,m,suffix,prefix);
}
i = i +Math.max(x,y);
}
return -1;
}
//j表示坏字符对应的模式串中的字符下标;m表示模式串长度
private int moveByGS(int j ,int m ,int[] suffix,boolean[] prefix){
int k = m - 1 - j;//好后缀长度
if(suffix[k] != -1) return j - suffix[k] +1;
for(int r = j +2 ; r <= m -1;++r){
if(prefix[m-r] == true){
return r;
}
}
return m ;
}
BMアルゴリズムのアイデアは、メインの文字列のパターンで文字列が不要な比較を減少させるために、戻ってさらにいくつかのよりパターン文字列のスライドと一致しない場合、パターン文字列自身の特性を使用することです