Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม

Z Algorithm


อัลกอริทึมนี้มีชื่อว่า Z Algorithm เพราะในอัลกอริทึมนี้ เราจำเป็นต้องสร้างอาร์เรย์ Z ขนาดของอาร์เรย์ Z เท่ากับขนาดข้อความ อาร์เรย์นี้ใช้เพื่อเก็บความยาวของสตริงย่อยที่ยาวที่สุดที่เป็นไปได้โดยเริ่มจากอักขระปัจจุบันของสตริงหลัก ในตอนแรก รูปแบบและข้อความหลักจะถูกเชื่อมด้วยสัญลักษณ์พิเศษซึ่งไม่มีอยู่ในข้อความและรูปแบบ หาก P คือรูปแบบ และ T เป็นข้อความหลัก หลังจากต่อกันแล้ว มันจะเป็น P$T (สมมติว่า $ ไม่มีอยู่ใน P และ T)

สำหรับอัลกอริทึมนี้ ความซับซ้อนของเวลาคือ O(m+n) เนื่องจาก m คือความยาวของรูปแบบ และ n คือความยาวของสตริงหลัก

อินพุตและเอาต์พุต

Input:
Main String: “ABAAABCDBBABCDDEBCABC”, Pattern: “ABC”
Output:
Pattern found at position: 4
Pattern found at position: 10
Pattern found at position: 18

อัลกอริทึม

fillZArray (conStr, ZArray)

อินพุต - conStr คือสตริงรูปแบบที่ต่อกันและข้อความหลัก ZArray เพื่อจัดเก็บดัชนีของสตริงย่อยที่ยาวที่สุดเท่าที่จะเป็นไปได้

ผลลัพธ์ − ZArray ที่เติมเต็ม

Begin
   n := length of conStr
   windLeft := 0 and windRight := 0

   for i := 1 to n, do
      if i > windRight, then
         windLeft := i and windRight := i
         while windRight < n AND conStr[windRight-windLeft] =
            conStr[windRight], do
            increase windRight by 1
         done
         ZArray[i] := windRight – windLeft
         decrease windRight by 1
      else
         k := i – windLeft
         if ZArray[k] < windRight – i +1, then
            ZArray[i] := ZArray[k]
         else
            windLeft := i
            while windRight < n AND conStr[windRight-windLeft] =
               conStr[windRight], do
               increase windRight by 1
            done
            ZArray[i] := windRight – windLeft
            decrease windRight by 1
   done
End

zAlgorithm(ข้อความ รูปแบบ)

อินพุต - ข้อความหลักและรูปแบบการค้นหา

ผลลัพธ์ − ตำแหน่งที่พบรูปแบบ

Begin
   conStr = concatenate pattern + “$” + text
   patLen := length of pattern
   len := conStr length
   fillZArray(conStr, ZArray)

   for i := 0 to len – 1, do
      if ZArray[i] = patLen, then
         print the location i – patLen – 1
   done
End

ตัวอย่าง

#include<iostream>
using namespace std;

void fillZArray(string conStr, int zArr[]) {
   int n = conStr.size();
   int windLeft, windRight, k;
   windLeft = windRight = 0;    //initially window size is 0

   for(int i = 1; i < n; i++) {
      if(i > windRight) {
         windLeft = windRight = i;     //window size is 0 but position to i
         while(windRight < n && conStr[windRight-windLeft] == conStr[windRight]) {
            windRight++;     //extend the right bound of window
         }
         zArr[i] = windRight-windLeft;
         windRight--;
      }else {
         k = i-windLeft;
         if(zArr[k] < windRight-i+1)
            zArr[i] = zArr[k];    //when kth item less than remaining interval
         else {
            windLeft = i;
            while(windRight < n && conStr[windRight - windLeft] == conStr[windRight]) {
               windRight++;
            }
            zArr[i] = windRight - windLeft;
            windRight--;
         }
      }
   }
}

void zAlgorithm(string mainString, string pattern, int array[], int *index) {
   string concatedStr = pattern + "$" + mainString;    //concat with special character
   int patLen = pattern.size();
   int len = concatedStr.size();
   int zArr[len];
   fillZArray(concatedStr, zArr);

   for(int i = 0; i<len; i++) {
      if(zArr[i] == patLen) {
         (*index)++;
         array[(*index)] = i - patLen -1;
      }
   }
}

int main() {
   string mainString = "ABAAABCDBBABCDDEBCABC";
   string pattern = "ABC";
   int locArray[mainString.size()];
   int index = -1;
   zAlgorithm(mainString, pattern, locArray, &index);

   for(int i = 0; i <= index; i++) {
      cout << "Pattern found at position: " << locArray[i]<<endl;
   }
}

ผลลัพธ์

Pattern found at position: 4
Pattern found at position: 10
Pattern found at position: 18