토큰의 텍스트에 따라 일부 특정 규칙이 있습니다.알고리즘에서는 C++

StackOverflow https://stackoverflow.com/questions/903133

  •  05-09-2019
  •  | 
  •  

문제

나는 프로그램 작성하는 것입니다 토큰의 텍스트 입력에 따라 일부 특정 규칙이 있습니다.내가 사용하는 C++니다.

규정

Letter 'a' should be converted to token 'V-A'
Letter 'p' should be converted to token 'C-PA'
Letter 'pp' should be converted to token 'C-PPA'
Letter 'u' should be converted to token 'V-U'

이 샘플에서 실시간 업데이 500+규칙은 이와 같습니다.는 경우에 저는 입력으로'noida 의 의 중심',그것은 토큰 다음과 같'V-A+C-PPA+V U'.내가 구현한 알고리즘에 대한 이것을 하고 있는지 확인하고 싶어 나는 일을 하고 있다.

알고리즘

모든 규칙에 보관됩니다 XML 파일이 해당 매핑합니다.뭔가

<rules>
  <rule pattern="a" token="V-A" />
  <rule pattern="p" token="C-PA" />
  <rule pattern="pp" token="C-PPA" />
  <rule pattern="u" token="V-U" />
</rules>

1-응용 프로그램이 시작되면,이것을 읽는 xml 파일을 유지에서 값'std::지도'.이 될 때까지 사용할 수 있는 응용 프로그램의 끝 부분(단일 패턴을 구현하).

2-반복하는 입력한 텍스트 문자입니다.각 문자,보이 일치합니다.발견하는 경우,더욱 욕심하고 더 많은 경기에 의해 다음의 문자를 입력된 텍스트입니다.이렇게까지 우리가 얻고 있는 아이 일치합니다.그래서를 위한 입력된 텍스트'noida 의 의 중심'먼저 찾아와 일치'a'.발견하는 경우를 얻을하려고 더 많이 일치하여 다음 문자 입력에서 텍스트입니다.그래서 그것은 것이 일치하려고'ap'고 없이 일치합니다.그래서 그것은 단지 반환합니다.

3-교체 문자'a'에서 입력된 텍스트로 토큰한다.

4-2 단계와 3 단계를 반복하십시오 함께 남아있는 캐릭터에 입력된 텍스트입니다.

여기서 더 간단한 단계의 설명

input-text = 'appu'
tokens-generated=''

// First iteration
character-to-match = 'a'
pattern-found = true

// since pattern found, going recursive and check for more matches
character-to-match = 'ap'
pattern-found = false

tokens-generated = 'V-A'

// since no match found for 'ap', taking the first success and replacing it from input text
input-text = 'ppu'

// second iteration
character-to-match = 'p'
pattern-found = true

// since pattern found, going recursive and check for more matches
character-to-match = 'pp'
pattern-found = true

// since pattern found, going recursive and check for more matches
character-to-match = 'ppu'
pattern-found = false

tokens-generated = 'V-A + C-PPA'

// since no match found for 'ppu', taking the first success and replacing it from input text
input-text = 'u'

// third iteration
character-to-match = 'u'
pattern-found = true

tokens-generated = 'V-A + C-PPA + V-U'  // we'r done!

질문

1-은 이 알고리즘을 잘 보이 이 문제에 대한 또는 더 나은 방법이 이 문제를 해결하기 위해?

2-는 경우 오른쪽 방법,std::지도가 좋은 선택이까요?또는 필요한가요를 만드는 내 자신의 키/값 컨테이너?

3-이 있는 라이브러리 사용할 수 있는 토큰 문자열을 좋아하십니까?

:)

도움이 되었습니까?

해결책

그래서 당신은 맵의 모든 토큰을 겪고 있습니까? 목록이나 배열을 사용할 수도 있습니다. 상관없이 비효율적 인 검색이 될 것입니다.

경기를 시작하거나 계속하는 데 적합한 토큰만을 찾는 훨씬 더 효율적인 방법은 그것들을 트리. 편지를 조회하면 그 편지를 첫 번째 편지로 가진 토큰 만 포함하는 하위 트리를 제공하고, 당신은 갈 수있는 한 아래로 아래로 검색합니다.


편집 : 이것을 조금 더 설명하겠습니다.

먼저, 나는 이것들에 익숙하지 않다고 설명해야합니다. std::map, 이름을 넘어서, 이것은 특정 프로그래밍 언어에서 특정 라이브러리의 세부 사항뿐만 아니라이 것들의 이론을 배우는 이유를 완벽하게 보여줍니다. 해당 라이브러리가 "지도"라는 이름을 잘못 사용하지 않는 한 (가능성이 낮음). , 이름 자체는 데이터 구조의 특성에 대해 많은 것을 알려줍니다. 예를 들어, 단일 키와지도가 주어지면 해당 키와 관련된 값을 매우 효율적으로 검색하고 반환 할 수있는 함수가있을 것이며, 목록을 제공 할 함수도있을 수 있습니다. /배열/모든 키의 모든 것이 자신의 코드를 사용하여 스스로 검색 할 수 있습니다.

데이터 구조에 대한 나의 해석은 키가 패턴이라고 부르는지도, 문자의 목록 (또는 배열 또는 그 특성)이며 값은 토큰이라는 것입니다. 따라서 전체 패턴이 주어지면 그와 관련된 토큰을 빠르게 찾을 수 있습니다.

불행히도, 이러한 맵은 XML 입력 형식을 내부 데이터 구조로 변환하는 것과 일치하지만 필요한 검색과 일치하지는 않습니다. 전체 패턴을 찾고있는 것이 아니라 패턴의 첫 번째 캐릭터를 찾고있는 일련의 토큰 세트를 생성 한 다음 패턴의 두 번째 문자를 조회합니다. 첫 번째 조회에서 생성 된 패턴 세트 내에서, 등등.

따라서 실제로 필요한 것은 단일 맵이 아니라 맵의 맵을 각각 단일 문자로 키워집니다. 최상위 레벨에서 "P"조회는 두 개의 키와 함께 새지도를 제공해야합니다. p, 생산 C-PPA 토큰과 "다른 것", C-PA 토큰. 이것은 사실상 트리 데이터 구조입니다.

이게 말이 되요?

이런 식으로 구문 분석 코드를 먼저 작성하여 시작하면 도움이 될 수 있습니다. 다른 사람이 필요한 조회를하기 위해 기능을 작성할 것이라고 상상해보십시오. 그는 정말 훌륭한 프로그래머이며 원하는 마법을 거의 할 수 있습니다. 구문 분석 코드를 작성하고 가능한 한 간단하고 깨끗하게 만드는 데 집중하여 필요한 이러한 임의의 기능을 사용하여 모든 인터페이스를 만듭니다 (사소한 일을하지 않고 하나의 기능으로 모든 것을 대체하십시오!). 이제 조회 기능을 살펴볼 수 있으며 데이터 구조에 액세스 해야하는 방법을 알려 드리면 필요한 데이터 구조 유형으로 이어질 수 있습니다. 일단 알아 내면로드하는 방법을 알아낼 수 있습니다.

다른 팁

  1. 이 방법은 일할 것이다-나는 확실하지 않다는 것은 효율적이지만,그것은 작업해야 합니다.

  2. 내가 사용하는 것 표준 std::지도보다는 자신의 시스템입니다.

  3. 가와 같은 도구 lex (나 flex 는)사용할 수 있습니다.해당 문제가 될 수 있는지 여부를 재생성 어휘 분석 것이라고 생성할 때 XML 사양의 변경합니다.는 경우 XML 사양은 변경되지 않은 종종,당신이 사용할 수 있습니다 같은 도구 lex 을 검사 및 매핑을 더 쉽게입니다.는 경우 XML 사양을 변경할 수 있습의 변덕에 그 프로그램을 사용하여,다음 lex 아마 미만 적합합니다.

다음과 같은 몇 가지 경고가 있습니다,우연히는 두 lexflex C 코드를 생성보다는 C++.

또한 것에서 찾고 생각 패턴 매칭 기술은 종류의 물건 egrep 특히 사용합니다.이의 공로가 있는 뭔가를 처리할 수 있는 런타임(기 egrep 그것은 모든 시간).또 갈 수 있습에 대한 스크립트 언어-Perl,Python,...거나 고려할 수 있습 같은 것 PCRE(Perl Compatible Regular Expressions)라이브러리입니다.

더 좋은 점은 Boost 라이브러리를 사용하려면 항상 Boost Tokenizer 라이브러리가 있습니다 ->. http://www.boost.org/doc/libs/1_39_0/libs/tokenizer/index.html

Regex (아마도 Boost :: Regex 라이브러리)를 사용할 수 있습니다. 모든 패턴이 단지 문자의 문자열이라면, "(a | p | pp | u)와 같은 regex는 탐욕스러운 일치를 찾을 수 있습니다. 그래서:

  1. 위의 패턴을 사용하여 regex_search를 실행하여 다음 경기를 찾습니다.
  2. 대체 텍스트를 std :: 맵에 연결하여 대체 텍스트를 가져옵니다.
  3. 일치하지 않은 소비 입력을 인쇄하고 출력에 텍스트를 교체 한 다음 나머지 입력에서 1을 반복하십시오.

그리고 끝났습니다.

조금 복잡해 보일 수 있지만 가장 효율적인 방법은 그래프를 사용하여 상태 차트를 나타내는 것입니다. 처음에 나는 생각했다 boost.statechart 도움이 될 것입니다. 그러나 나는 그것이 실제로 적절하지 않다고 생각했습니다. 이 방법은 단순한 std :: 맵을 사용하는 규칙이 많으면 가능한 문자 수가 제한되어 있고 읽을 텍스트의 길이가 상당히 높다는 점이 더 효율적일 수 있습니다.

어쨌든 간단한 그래프를 사용합니다.

0) "시작"정점으로 그래프를 만듭니다

1) XML 구성 파일을 읽고 필요할 때 정점을 만듭니다 ( "문자 세트"(예 : "PP")에서 추가 1 (예 : "PPA")으로 전환). 각 정점 내부에 전환 테이블을 다음 정점에 저장하십시오. "키 텍스트"가 완료되면 정점을 최종으로 표시하고 결과 텍스트를 저장합니다.

2) 이제 텍스트를 읽고 그래프를 사용하여 해석하십시오. "시작"정점에서 시작하십시오. ( *) 테이블을 사용하여 하나의 문자를 해석하고 새로운 정점으로 이동합니다. 새 정점을 선택하지 않으면 오류가 발행 될 수 있습니다. 그렇지 않으면, 새로운 정점이 최종 인 경우 결과 텍스트를 인쇄하고 다시 점프하여 vertex를 시작하십시오. 더 이상 해석 할 텍스트가 없을 때까지 (*)로 돌아갑니다.

당신은 사용할 수 있습니다 boost.graph 그래프를 표현하기 위해서는 필요한 것이 지나치게 복잡하다고 생각합니다. 자신만의 맞춤형 표현을 만드십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top