データ構造の文字列、単純なパターンマッチング、KMPパターンマッチングに関する知識

1.一連の基本的な知識

1.文字列の定義:

文字列(文字列)は、0個以上の文字の有限シーケンスであり、文字列とも呼ばれます。
一般记为:
s="a1a2.......an"(a>=0)

注:sが文字列名である場合、二重引用符で囲まれた文字のシーケンスは文字列値であり、二重引用符自体は文字列の内容に属しません。ai(1 <= i <= n)は任意の文字で、文字列の要素と呼ばれ、文字列を構成する基本単位です。iは文字列全体におけるそのシリアル番号です。nは文字列の長さです。つまり、文字列には文字数。

2.スペース文字列:

スペースのみを含む文字列。スペース文字列の長さは空の文字列とは異なります。

3.空の文字列:

空の文字列–長さがゼロの文字列は、空の文字列と呼ばれます。2つの二重引用符を直接使用して「」を示すことができます。

4.文字列とメイン文字列:

文字列内の任意の連続した文字で構成される部分列は、文字列の部分文字列と呼ばれます。サブストリングを含むストリングは、サブストリングのメインストリングです。

5.文字列の比較:

これは、C言語でのstrcmpの使用法に似ており、比較にASCIIエンコーディングを使用しています。

次の2つの文字列が与えられた場合:s =” a1a2……an”、t =” b1b2……bm”、次の条件のいずれかが満たされた場合、s <t:

1。n <m、およびai = bi(i = 1、2、...、n)、nはs文字列の長さ、sはt文字列の長さ、前の文字列は同じ、ただしs文字列の長さt文字列よりも小さいということは、s文字列がt文字列よりも小さいことを意味します
2。特定のk≤min(m、n)があります。これはk> 1の場合であり、最初の2つの文字列からai = bi(i = 1、2、...、k-1)、ak <bkの場合文字は等しくなくなり始めます。つまり、a1!= B1の場合、a1とb1のサイズのみが直接比較されます。

6.文字列の関連データ構造:

ADT 串(string)
Data
    串中元素仅由一个字符组成,相邻元素具有前驱和后继关系。
Operation
    StrAssign(T, *chars):        生成一个其值等于字符串常量chars的串T
    StrCopy(T, S):               串S存在,由串S复制得串T
    ClearString(S):              串S存在,将串清空。
    StringEmpty(S):              若串S为空,返回true,否则返回false。
    StrLength(S):                返回串S的元素个数,即串的长度。
    StrCompare(S, T):            若S>T,返回值>0,若S=T,返回0,若S<T,返回值<0。
    Concat(T, S1, S2):           用T返回由S1和S2联接而成的新串。
    SubString(Sub, S, pos, len): 串S存在,1≤pos≤StrLength(S),
                                 且0≤len≤StrLength(S)-pos+1,用Sub返
                                 回串S的第pos个字符起长度为len的子串。
    Index(S, T, pos):            串S和T存在,T是非空串,1≤pos≤StrLength(S)。
                                 若主串S中存在和串T值相同的子串,则返回它在主串S中
                                 第pos个字符之后第一次出现的位置,否则返回0。
    Replace(S, T, V):            串S、T和V存在,T是非空串。用V替换主串S中出现的所有
    

2.文字列の保存

1.順次保管構造:

文字列のシーケンシャルストレージ構造は、連続したアドレスストレージユニットのグループを使用して文字列を格納することです。文字列には、通常、固定長配列(配列)で定義される固定長の記憶領域を割り当てます。

注:C言語で文字配列を定義するときは、コンパイラーが自動的に '\ 0'を追加するため、文字列の長さを決定するのに便利なので、追加の長さを追加する必要があります。ただし、この '\ 0'は文字列の長さに含まれません。

2.チェーンストレージ構造:

リンクリストを使用して文字列を格納する場合、各ノードには2つのフィールドがあります。1つはデータフィールド(データ)で、もう1つはポインターフィールド(次へ)です。データフィールド(data)-文字列内の文字を格納します。ポインタフィールド(次)–後続ノードのアドレスを格納します。

:ノードは文字または文字配列を格納できますが、文字列の特殊な性質により、リンクリストストレージを文字列の格納方法として使用することも実用的ではないため、使用量は少なくなります。

3.単純なパターンマッチングアルゴリズム

これは、メイン文字列をトラバースし、次に、照合する文字列をサブ文字列と比較します。最初に、メイン文字列と照合するサブ文字列の最初の文字を照合します。照合が成功した場合、2つの文字列の座標は++となり、照合は行われません。成功すると、メイン文字列の座標は一致の最初の座標に戻ります。一致する文字列の座標はクリアされます。一致する座標が一致するサブ文字列の長さと等しい場合、一致は成功したと証明されます。一致後のメイン文字列の最初の座標が返され、それ以外の場合は返されます0
int Index(String S,String T,int pos)       //定义了一个主串,子串,开始查找的位置
 {
      int i=pos;      //主串的查找位置,从该位置以后开始查找是否有字串
     int j=1;          //此处不太理解  为啥其实位置是1,感觉应该是0开始的
     while(i<=S[0]&&j<=T[0])
      {  
	if(S[i]==T[j])//判断两个字符串是否相等
 	{
 		 ++i;         //两个相等时自加1,当判断出字串时,j=T的长度+1
 		 ++j;
 	} 
 	else{
 		 i=i-j+2;    //两个字符不相等时,i-j的相当于返回了当前字串开头的那个字母的前一个字符,然后加2,就相当于从主串的下一个字符作为字串开头
 	 	 j=1;       //这时被匹配的字串回到首位
 	      }
 	 }
   if(j>T[0])
 	 return i-T[0];
   else
	return 0;
 }

ただし、メイン文字列内の多数の一致が毎回等しくないことが判明した場合は、再度一致させます。このサイクルは多くの時間を浪費するため、KMPパターンマッチングアルゴリズムがあります。

3. KMPパターンマッチング

従来の単純なパターンマッチングアルゴリズムでは、主文字列がiから一致すると、一致がj位置に到達すると不一致が見つかり、主文字列がi + 1位置に戻り、一致文字列が0位置に戻ります。これにより、一致効率が低くなります。時間の複雑さは高いです。

KMPがj位置と一致しない場合、メイン文字列は移動しません。一致文字列は、まず現在の位置からプレフィックスサブ文字列とサフィックスサブ文字列の最大一致文字列長を計算します。KMPアルゴリズムの本質は、次のプロセスを見つけることです。

1.次のアレイを見つける方法

ここに画像の説明を挿入

ここに画像の説明を挿入
:1.私の理解では、接頭辞の後に文字が必要であり、文字全体を接頭辞にすることはできません。同様に、接尾辞の前に文字が必要です。

例:文字列が「aaaa」、接頭辞が「aa」、接尾辞が「aa」の場合、「aaa」にはできません
。2 パターン文字列Tの場合、次の[j]はTの最初のj文字の部分文字列を表しますその中で、プレフィックスとサフィックスの最も長い共通の文字列の長さは+1です。

コードは次のとおりです。

void get_next(char T[], int *next)
{
 
 int i,j;
 i = 1;
 j = 0;
 next[1] = 0;
 while(i < T[0])      //T[0]是子串T的长度
 {       
  //T[i]表示后缀的单个字符
  //T[j]表示前缀的单个字符
  	if( j==0 || T[i] == T[j])    
  	{
  	 ++i;
  	 ++j;
   	next[i] = j;
  	}
  	else
	{
  	 j = next[j];
 	 }
 }
}

全体的なKMPコードは次のとおりです。


 
int Index_KMP(char S[], char T[], int pos)
{
 int i = pos;
 int j = 1;
 int next[255];
 get_next(T, next);
 
 while(i <= S[0] && j <= T[0]){
  //相对于朴素算法,增加了一个j==0的判断
  if( j==0 || S[i] == T[j]){
   ++i;
   ++j;
  }else{
   //j回退到合适的位置,i的值不变
   j = next[j];
  }
 }
 if( j>T[0]){
  return i-T[0];
 }else{
  return 0;
 }
}
オリジナルの記事を10件公開 Likes2 訪問数217

おすすめ

転載: blog.csdn.net/dfwef24t5/article/details/105441813
おすすめ