Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Aho-Corasick自动机中寻找循环_C++_Algorithm - Fatal编程技术网

C++ 在Aho-Corasick自动机中寻找循环

C++ 在Aho-Corasick自动机中寻找循环,c++,algorithm,C++,Algorithm,我正面临着一个问题,这个问题应该通过使用Aho Corasick自动机来解决。我得到了一组单词(由“0”或“1”组成)-模式,我必须决定是否有可能创建无限文本,其中不包含任何给定模式。我认为,解决方案是创建一个Aho Corasick自动机并搜索一个没有匹配状态的循环,但我不能提出一个好的方法来做到这一点。我曾想过使用DFS搜索状态图,但我不确定它是否有效,我有一个实现问题-让我们假设,我们处于一个状态,该状态有一个“1”边-但该边指向的状态被标记为匹配-因此我们不能使用该边,我们可以尝试失败链

我正面临着一个问题,这个问题应该通过使用Aho Corasick自动机来解决。我得到了一组单词(由“0”或“1”组成)-模式,我必须决定是否有可能创建无限文本,其中不包含任何给定模式。我认为,解决方案是创建一个Aho Corasick自动机并搜索一个没有匹配状态的循环,但我不能提出一个好的方法来做到这一点。我曾想过使用DFS搜索状态图,但我不确定它是否有效,我有一个实现问题-让我们假设,我们处于一个状态,该状态有一个“1”边-但该边指向的状态被标记为匹配-因此我们不能使用该边,我们可以尝试失败链接(当前状态没有“0”边)-但我们还必须记住,我们不能使用当前状态的失败链接所指向状态的“1”边缘

有人能纠正我并告诉我怎么做吗?我用C++编写了Aho Corasick,我确信它是有效的,我也理解整个算法。 以下是基本代码:

class AhoCorasick
{

static const int ALPHABET_SIZE = 2;

struct State
{
  State* edge[ALPHABET_SIZE];
  State* fail;
  State* longestMatchingSuffix;
  //Vector used to remember which pattern matches in this state.
  vector< int > matching;
  short color;

  State()
  {
    for(int i = 0; i < ALPHABET_SIZE; ++i)
      edge[i] = 0;
    color = 0;
  }

  ~State()
  {
    for(int i = 0; i < ALPHABET_SIZE; ++i)
    {
      delete edge[i];
    }
  }
};

private:
  State root;
  vector< int > lenOfPattern;
  bool isFailComputed;

  //Helper function used to traverse state graph.
  State* move(State* curr, char letter)
  {
    while(curr != &root && curr->edge[letter] == 0)
    {
      curr = curr->fail;
    }
    if(curr->edge[letter] != 0)
      curr = curr->edge[letter];
    return curr;
  }

  //Function which computes fail links and longestMatchingSuffix. 
  void computeFailLink()
  {
    queue< State* > Q;
    root.fail = root.longestMatchingSuffix = 0;
    for(int i = 0; i < ALPHABET_SIZE; ++i)
    {
      if(root.edge[i] != 0)
      {
        Q.push(root.edge[i]);
        root.edge[i]->fail = &root;
      }
    }
    while(!Q.empty())
    {
      State* curr = Q.front();
      Q.pop();
      if(!curr->fail->matching.empty())
      {
        curr->longestMatchingSuffix = curr->fail;
      }
      else
      {
        curr->longestMatchingSuffix = curr->fail->longestMatchingSuffix;
      }
      for(int i = 0; i < ALPHABET_SIZE; ++i)
      {
        if(curr->edge[i] != 0)
        {
          Q.push(curr->edge[i]);
          State* state = curr->fail;
          state = move(state, i);
          curr->edge[i]->fail = state;
        }
      }
    }
    isFailComputed = true;
  }

public:
  AhoCorasick()
  {
    isFailComputed = false;
  }

  //Add pattern to automaton.
  //pattern - pointer to pattern, which will be added
  //fun - function which will be used to transform character to 0-based index.
  void addPattern(const char* const pattern, int (*fun) (const char *))
  {
    isFailComputed = false;
    int len = strlen(pattern);
    State* curr = &root;
    const char* pat = pattern;
    for(; *pat; ++pat)
    {
      char tmpPat = fun(pat);
      if(curr->edge[tmpPat] == 0)
      {
        curr = curr->edge[tmpPat] = new State;
      }
      else
      {
        curr = curr->edge[tmpPat];
      }
    }
    lenOfPattern.push_back(len);
    curr->matching.push_back(lenOfPattern.size() - 1);
  }
};

int alphabet01(const char * c)
{
  return *c - '0';
}
class属性
{
静态常数int字母表大小=2;
结构状态
{
状态*边缘[字母表大小];
国家*失败;
状态*最长匹配uffix;
//用于记住在此状态下匹配的模式的向量。
向量匹配;
短颜色;
国家()
{
对于(int i=0;ilenOfPattern;
bool-isFailComputed;
//用于遍历状态图的辅助函数。
状态*移动(状态*当前,字符字母)
{
while(curr!=&root&&curr->edge[字母]==0)
{
当前=当前->失败;
}
如果(当前->边缘[字母]!=0)
当前=当前->边缘[字母];
返回货币;
}
//计算失败链接和最长匹配uffix的函数。
void computeFailLink()
{
队列Q;
root.fail=root.longestMatchingSuffix=0;
对于(int i=0;ifail=&root;
}
}
而(!Q.empty())
{
状态*curr=Q.front();
Q.pop();
如果(!curr->fail->matching.empty())
{
curr->longestmachingsuffix=curr->fail;
}
其他的
{
curr->longestmachingsuffix=curr->fail->longestmachingsuffix;
}
对于(int i=0;i边缘[i]!=0)
{
推送(电流->边缘[i]);
状态*状态=当前->失败;
状态=移动(状态,i);
电流->边缘[i]->故障=状态;
}
}
}
isFailComputed=true;
}
公众:
阿霍科拉西克()
{
isFailComputed=false;
}
//向自动机添加模式。
//模式-指向将要添加的模式的指针
//fun-用于将字符转换为基于0的索引的函数。
void addPattern(常量字符*常量模式,int(*fun)(常量字符*)
{
isFailComputed=false;
int len=strlen(模式);
状态*curr=&root;
常量字符*pat=模式;
对于(;*pat;++pat)
{
char tmpPat=乐趣(pat);
如果(当前->边缘[tmpPat]==0)
{
当前=当前->边缘[tmpPat]=新状态;
}
其他的
{
当前=当前->边缘[tmpPat];
}
}
Lenof模式。推回(len);
curr->matching.push_back(lenOfPattern.size()-1);
}
};
int alphabet01(常量字符*c)
{
返回*c-'0';
}

我没有仔细阅读您的代码,但我知道非常简单高效的实现

首先,让我们向树添加字典后缀链接(它们的描述可以在维基百科中找到)。然后,您必须查看所有树,并以某种方式将匹配节点和具有Dict后缀链接的节点标记为坏节点。对这些操作的解释是显而易见的:您不需要所有匹配的节点,也不需要包含匹配后缀的节点


现在有了一个没有任何匹配节点的Aho-Corasick树。如果您只是在生成的树上运行DFS algo,您将得到您想要的

请发布一份构建自动机的代码草图(请不要完整的代码-只需关键部分):在构建自动机时,修改代码以查找循环可能很容易。我不确定字典后缀链接是什么意思,但我非常确定,我完全按照你说的去做-在你回复前几天,我已经实现了类似的东西-但它不起作用-几天后我意识到了原因-我正在使用只使用一个字母构建的循环。做得好。字典后缀链接指的是指向前一个后缀的链接,即完整单词。