알고리즘 서론 - AC 자동 동기
AC 자동 동 기 는 비교적 효율 적 인 다 중 모드 매 칭 알고리즘 이다.KMP 가 패턴 문자열 에 있 는 상태 이동 알고리즘 과 유사 합 니 다. AC 자동 동 기 는 trie 트 리 에 상태 이동 을 만들어 서 일치 하 는 문자열 을 한 번 훑 어보 면 모든 패턴 문자열 을 찾 을 수 있 습 니 다.AC 자동 동 기 는 일반적으로 다음 과 같은 세 가지 단계 가 있다. 우선, 모든 패턴 문자열 에 trie 트 리 를 만든다.그 다음 에 trie 트 리 의 모든 노드 에 대해 가장 긴 접미사 에 대응 하 는 접두사 문자열 을 포인터 로 하여 AC 자동 동 기 를 만 듭 니 다.마지막 단 계 는 AC 자동 동기 에 텍스트 문자열 을 일치 시 킵 니 다.
제목 링크:http://hihocoder.com/problemset/problem/1036?sid=786758
참조 코드:
#include <iostream>
#include <queue>
#include <string>
#include <string.h>
using namespace std;
#define size 26
struct node
{
node *fail; //
node *next[size]; //Tire 26 , 26
int count; //
node()
{
fail = NULL;
count = 0;
memset(next, NULL, sizeof(next));
}
};
void Insert(node *root, string str)
{
node *p = root;
int i = 0, index;
for (int i = 0; i < str.length(); i++)
{
index = str[i] - 'a';
if (p->next[index] == NULL)
p->next[index] = new node();
p = p->next[index];
}
p->count++;
}
void GetFail(node *root)
{
int i;
root->fail = NULL;
queue<node*> q;
q.push(root);
while (q.empty() == false)
{
node *temp = q.front();
q.pop();
node *p = NULL;
for (i = 0; i<size; i++)
{
if (temp->next[i] != NULL)
{
if (temp == root)
temp->next[i]->fail = root;
else
{
p = temp->fail;
while (p != NULL)
{
if (p->next[i] != NULL)
{
temp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if (p == NULL)
temp->next[i]->fail = root;
}
q.push(temp->next[i]);
}
}
}
}
bool Query(node *root, string str)
{
int cnt = 0, index;
node *p = root;
for (int i = 0; i < str.length(); i++)
{
index = str[i] - 'a';
while (p->next[index] == NULL && p != root)
p = p->fail;
p = p->next[index];
p = (p == NULL) ? root : p;
node *temp = p;
while (temp != root)
{
if (temp->count != 0)
return true;
else
temp = temp->fail;
}
}
return false;
}
int main()
{
int n;
node *root = new node();
cin >> n;
string keyword;
while (n--)
{
cin >> keyword;
Insert(root, keyword);
}
GetFail(root);
string str;
cin >> str;
if (Query(root, str))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
위의 코드 는 이론 적 으로 정확 한 코드 이지 만 이것 을 제출 하면 시간 이 초과 되 고 84 줄 while 를 if 로 수정 하면 통과 할 수 있 지만 수정 후 논리 적 으로 잘못된 코드 입 니 다.
다음은 AC 자동 동기 기능 확장 코드 를 드 립 니 다.
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <string.h>
#include <fstream>
using namespace std;
#define size 26
struct ACNode
{
ACNode *fail; //
ACNode *next[size]; //Tire 26 , 26
int count; // ,
int patternNo; // ,
ACNode()
{
fail = NULL;
count = 0;
patternNo = -1;
memset(next, NULL, sizeof(next));
}
};
void Insert(ACNode *root, string str, int patterNo)
{
ACNode *p = root;
int i = 0, index;
for (int i = 0; i < str.length(); i++)
{
index = str[i] - 'a';
if (p->next[index] == NULL)
p->next[index] = new ACNode();
p = p->next[index];
}
p->count++;
p->patternNo = patterNo;
}
void GetFail(ACNode *root)
{
int i;
root->fail = NULL;
queue<ACNode*> q;
q.push(root);
while (q.empty() == false)
{
ACNode *temp = q.front();
q.pop();
ACNode *p = NULL;
for (i = 0; i<size; i++)
{
if (temp->next[i] != NULL)
{
if (temp == root)
temp->next[i]->fail = root;
else
{
p = temp->fail;
while (p != NULL)
{
if (p->next[i] != NULL)
{
temp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if (p == NULL)
temp->next[i]->fail = root;
}
q.push(temp->next[i]);
}
}
}
}
int Query(ACNode *root, string str, vector<string> &keySet)
{
int cnt = 0, index;
ACNode *p = root;
for (int i = 0; i < str.length();i++)
{
index = str[i] - 'a';
while (p->next[index] == NULL && p != root)
p = p->fail;
p = p->next[index];
p = (p == NULL) ? root : p;
ACNode *temp = p;
while (temp != root)
{
if (temp->count>0)
{
int patternNo = temp->patternNo;
int patternLength = keySet[patternNo].length();
cout << i - patternLength + 1 << " " << keySet[patternNo] << endl;
cnt += temp->count;
}
temp = temp->fail;
}
}
return cnt;
}
int main()
{
ifstream in(".\\input.txt");
cin.rdbuf(in.rdbuf());
int n;
ACNode *root = new ACNode();
cin >> n;
string keyword;
vector<string> keySet;
for (int i = 0; i < n;i++)
{
cin >> keyword;
keySet.push_back(keyword);
Insert(root, keyword,i);
}
GetFail(root);
string str;
cin >> str;
Query(root, str, keySet);
return 0;
}
참고 블 로그:http://www.cppblog.com/mythit/archive/2009/04/21/80633.html http://www.cnblogs.com/xudong-bupt/p/3433506.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.