📜  Moore Machines在C ++中的实现

📅  最后修改于: 2021-08-27 04:53:50             🧑  作者: Mango

摩尔机:摩尔机基本上是DFA,其输出与每个状态相关联。这些机器可用于多种任务,例如计算给定字符串特定子字符串的出现次数,查找二进制数的2的补码等。

摩尔机的工作原理:

  • 它具有与每个状态关联的输出。
  • 接受输入后,它将进入下一个状态。
  • 到达下一个状态时,它将打印下一个状态的输出。
  • 这一直持续到输入结束为止。

摩尔机的一些应用

应用1:
给定一个字符串s组成的AB,以及串“羊毛”,任务是计算给定字符串在给定的子串str的发生使用摩尔机

例子:

方法:

该问题所需的摩尔机由下式给出:

机器的转换表如下:

要实现这一点,请创建一个用于将输入映射到其下一个状态的结构:

struct item
{
     int value;
     State* next;
};

然后,将此结构作为类State的数据成员包括在内。该类具有三个数据成员:

  • Input_1:这是上面定义的type类型的变量。它将第一种输入类型“ a”映射到其下一个状态。
  • Input_2:这也是item类型的变量。它将第二种类型的输入“ b”映射到其下一个状态。
  • m_out:这是与摩尔机的每个状态关联的输出。

该类的每个对象都表现为一个状态。它接受输入并进入适当的下一个状态。要进入下一个状态,可以使用对象指针。每个对象还具有与之关联的输入。

以下成员函数将用于处理此数据:

  • Initialize():通过输入和相应的下一个状态来初始化类对象(状态)。
  • Transition():这充当计算机的过渡表。它从输入字符串获取一个字符,并将其传递到当前状态,然后在生成输出后进入相应的下一个状态。
  • Traverse():此函数接受输入字符串,然后将一个字符一个字符传递到转换函数并返回输出字符串。
  • mooreOut():此函数定义所需的状态(对象)并将其初始化为所需的值。然后将输入字符串传递给遍历函数并接收输出字符串。
  • countStr():此函数计算输出字符串中1的出现次数并返回。

下一步是存储计算机的当前状态,同时将字符串输入传递给它。这可以通过使用静态Object指针作为数据成员:

下面是上述方法的实现:

C++14
// C++ program for the above approach
  
#include 
using namespace std;
  
// Define a class named State
class State {
private:
    // Item
    struct item {
        char value;
        State* next;
    };
  
    // Three states
    item Input1;
    item Input2;
    char m_out;
  
public:
    // Constructor
    State()
        : Input1{ ' ', nullptr },
          Input2{ ' ', nullptr },
          m_out{ ' ' }
    {
    }
  
    // Member functions
    static State* m_ptr;
    void Initialize(item input1,
                    item input2,
                    char out);
    static char Transition(char x);
    static string Traverse(string& str,
                           int n);
};
  
// Global object pointer points to
// current state
State* State::m_ptr{ nullptr };
  
// Function that initializes the states
// with appropriate values
void State::Initialize(item input1,
                       item input2,
                       char out)
{
    Input1 = input1;
    Input2 = input2;
    m_out = out;
}
  
// Transition function that takes each
// character of string
char State::Transition(char x)
{
    char ch{};
  
    // Prints the output
    if ((*m_ptr).Input1.value == x) {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input1.next;
    }
    else {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input2.next;
    }
  
    // Return ch
    return ch;
}
  
// Takes the whole string and pass
// it through machine
string State::Traverse(string& str,
                       int n)
{
    string str1{};
  
    // Add all the transition state to
    // the string str1
    for (int i = 0; i < n; i++)
        str1 += Transition(str[i]);
  
    // Append output
    str1 += (*m_ptr).m_out;
    cout << (*m_ptr).m_out << endl;
  
    // Return str1
    return str1;
}
  
// Function that create states and
// produce output
string mooreOut(string str, int n)
{
    State q1, q2, q3, q4;
  
    // Initializing the states
    q1.Initialize({ 'a', &q2 },
                  { 'b', &q1 }, '0');
    q2.Initialize({ 'a', &q2 },
                  { 'b', &q3 }, '0');
    q3.Initialize({ 'a', &q2 },
                  { 'b', &q4 }, '0');
    q4.Initialize({ 'a', &q2 },
                  { 'b', &q1 }, '1');
    State::m_ptr = &q1;
  
    // Traverse the string str1
    string str1{ State::Traverse(str, n) };
    return str1;
}
  
// Function that counts the occurences
// of 1 in the output string
int countStr(string& str, int n)
{
    int count{};
  
    // Count the 1s in str
    for (int i = 0; i < n; i++) {
        if (str[i] == '1')
            count++;
    }
  
    // Return count
    return count;
}
  
// Driver Code
int main()
{
  
    // Given string
    string str{ "babbabbabbb" };
  
    int n{ static_cast(str.length()) };
  
    // Function Call
    string str1{ mooreOut(str, n) };
    int n1{ static_cast(str.length()) };
  
    // Print the count of substring
    cout << "abb occurs " << countStr(str1, n1)
         << " times\n";
    return 0;
}


C++
// C++ program for the above approach
  
#include 
using namespace std;
  
// Define a class named State
class State {
private:
    struct item {
        char value;
        State* next;
    };
    item Input1;
    item Input2;
    char m_out;
  
public:
    // Constructors
    State()
        : Input1{ ' ', nullptr },
          Input2{ ' ', nullptr },
          m_out{ ' ' }
    {
    }
    static State* m_ptr;
  
    // Member Functions
    void Initialize(item input1,
                    item input2,
                    char out);
    static char Transition(char x);
    static string Traverse(string& str,
                           int n);
};
  
// Global object pointer points to
// current state
State* State::m_ptr{ nullptr };
  
// Function that initializes the states
// with appropriate values
void State::Initialize(item input1,
                       item input2,
                       char out)
{
    Input1 = input1;
    Input2 = input2;
    m_out = out;
}
  
// Transition function takes each
// character of string
char State::Transition(char x)
{
    char ch{};
  
    // Prints the output
    if ((*m_ptr).Input1.value == x) {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input1.next;
    }
    else {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input2.next;
    }
  
    // Return ch
    return ch;
}
  
// Takes the whole string and passes
// through machine
string State::Traverse(string& str, int n)
{
    string str1{};
  
    // Add all the transition state to
    // the string str1
    for (int i = n - 1; i >= 0; i--) {
        str1 += Transition(str[i]);
    }
  
    // To read the characters from end
    // therefore we need to reverse
    reverse(str1.begin(), str1.end());
  
    return str1;
}
  
// Function to create states and
// produce output
string mooreOut(string str, int n)
{
    State q1, q2, q3;
  
    // Initializing the states
    q1.Initialize({ '0', &q1 },
                  { '1', &q2 }, '0');
    q2.Initialize({ '0', &q2 },
                  { '1', &q3 }, '1');
    q3.Initialize({ '0', &q2 },
                  { '1', &q3 }, '0');
    State::m_ptr = &q1;
    return State::Traverse(str, n);
}
  
// Driver Code
int main()
{
    // Given string
    string str{ "111010000" };
    int n{ static_cast(str.length()) };
  
    // Function Call
    string str1{ mooreOut(str, n) };
  
    // Print the output
    cout << "2's complement: " << str1;
    return 0;
}


输出:
000010010010
abb occurs 3 times


时间复杂度: O(N)
辅助空间: O(N)

应用2:
给定二进制字符串str ,任务是找到给定字符串str的2s补码。

方法:想法是从最右边的位开始,然后将其传递到提供输出的机器中。这样传递整个字符串,从右到左。可以观察到以下观察结果:

例如:给定的字符串是“ 111010000”。现在,2s补语由(str)+ 1的1s补码给出。因此,

str =           "111010000"
1s compliment = "000101111"
                +        1
---------------------------
2s compleemnt =  000110000

在这里我们可以看到,从最右边的位开始,这些位以相同的方式被复制,直到出现1。之后,所有位都反转。

因此,我们的想法是定义一个摩尔机,从最右边开始输入。只要该位为0,它就会给出相同的输出(0) 。当遇到1,那么它给1为。此后,对于任何取为输入的位,其逆值都将作为输出。

以下是针对该问题的摩尔机:

要首先实现这一点,请映射此机器的转换表。需要三个状态,即开头定义的State类的三个对象:

  • State1 => Initailize({‘0’,&State1},{‘1’,&State2},’0’)
  • State2 =>初始化({‘0’,&State2},{‘1’,&State3},’1’)
  • State3 =>初始化({‘0’,&State2},{‘1’,&State3},’0’)

初始化后,需要像上面定义的那样的转换函数。它接受一个输入,并输出当前状态的输出,并使用上面定义的转换表通过将输入映射到下一个状态而进入下一个状态。然后,要遍历字符串,过渡将从最右边的位开始,一直到最左边的位。

下面是上述方法的实现:

C++

// C++ program for the above approach
  
#include 
using namespace std;
  
// Define a class named State
class State {
private:
    struct item {
        char value;
        State* next;
    };
    item Input1;
    item Input2;
    char m_out;
  
public:
    // Constructors
    State()
        : Input1{ ' ', nullptr },
          Input2{ ' ', nullptr },
          m_out{ ' ' }
    {
    }
    static State* m_ptr;
  
    // Member Functions
    void Initialize(item input1,
                    item input2,
                    char out);
    static char Transition(char x);
    static string Traverse(string& str,
                           int n);
};
  
// Global object pointer points to
// current state
State* State::m_ptr{ nullptr };
  
// Function that initializes the states
// with appropriate values
void State::Initialize(item input1,
                       item input2,
                       char out)
{
    Input1 = input1;
    Input2 = input2;
    m_out = out;
}
  
// Transition function takes each
// character of string
char State::Transition(char x)
{
    char ch{};
  
    // Prints the output
    if ((*m_ptr).Input1.value == x) {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input1.next;
    }
    else {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input2.next;
    }
  
    // Return ch
    return ch;
}
  
// Takes the whole string and passes
// through machine
string State::Traverse(string& str, int n)
{
    string str1{};
  
    // Add all the transition state to
    // the string str1
    for (int i = n - 1; i >= 0; i--) {
        str1 += Transition(str[i]);
    }
  
    // To read the characters from end
    // therefore we need to reverse
    reverse(str1.begin(), str1.end());
  
    return str1;
}
  
// Function to create states and
// produce output
string mooreOut(string str, int n)
{
    State q1, q2, q3;
  
    // Initializing the states
    q1.Initialize({ '0', &q1 },
                  { '1', &q2 }, '0');
    q2.Initialize({ '0', &q2 },
                  { '1', &q3 }, '1');
    q3.Initialize({ '0', &q2 },
                  { '1', &q3 }, '0');
    State::m_ptr = &q1;
    return State::Traverse(str, n);
}
  
// Driver Code
int main()
{
    // Given string
    string str{ "111010000" };
    int n{ static_cast(str.length()) };
  
    // Function Call
    string str1{ mooreOut(str, n) };
  
    // Print the output
    cout << "2's complement: " << str1;
    return 0;
}
输出:
2's complement: 000110000


时间复杂度: O(N),其中N是给定二进制字符串的长度。
辅助空间: O(N)