2015-05-23 4 views
1

Я пытаюсь найти шаблон регулярного выражения, чтобы соответствовать слову с некоторыми заданными символами. Но каждый символ должен использоваться только один раз. Например, если я данной "yrarbil" (библиотека назад), он должен соответствовать этим:Как совместить слово с использованием заданного символа только один раз

  • библиотека
  • Rar
  • Lib
  • rarlib

Но это должно не соответствуют следующим:

  • libraryy («у» используется несколько раз, чем данные)
  • библиотеки («я» используется несколько раз, чем данные, а также «эс» не дают вообще)

Я обыскал все вокруг, но лучше всего я мог найти код, соответствующий слову, но тот же символ используется больше, чем столько раз, сколько ему было дано. Спасибо.

P.S: Если это невозможно сделать в регулярном выражении (я как-то на нем, как вы можете видеть), что было бы лучшим способом сопоставить такое слово, как это программно?

+1

Регулярное выражение для этого не будет эффективным. Решением будет просто подсчет символов вашего списка. –

+0

Я думаю, что это должно быть сделано вручную, а не регулярным выражением, но на каком языке вы лучше понимаете C++ или C#? – ahmedsafan86

+0

@shA.t библиотека действительна, потому что при данном слове yrarbil r используется дважды ... –

ответ

1

"библиотека" сбивает с толку, потому что она имеет 2 пометов г. Но это решение, по моему мнению.

Простое создание map<char, int> это будет хранить количество символов в шаблоне. Затем мы будем генерировать map<char, int> для проверки слова, он также будет содержать счет каждого символа, а затем перебирать по карте, если какой-либо символ имеет больше счетчика, чем тот же символ на карте шаблона, который он не соответствует, также если он не найдено вообще, то это тоже не соответствует.

При необходимости код в C# с использованием системы; с использованием System.Collections.Generic; с использованием System.Linq; с использованием System.Text; с использованием System.Threading.Tasks;

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static bool Match(string pattern, string toMatch) 
     { 
      Dictionary<char, int> patternMap = new Dictionary<char, int>(); 
      Dictionary<char, int> toMatchMap = new Dictionary<char, int>(); 

      foreach (char ch in pattern) 
      { 
       if (patternMap.ContainsKey(ch)) 
        ++patternMap[ch]; 
       else 
        patternMap[ch] = 1; 
      } 
      foreach (char ch in toMatch) 
      { 
       if (toMatchMap.ContainsKey(ch)) 
        ++toMatchMap[ch]; 
       else 
        toMatchMap[ch] = 1; 
      } 

      foreach (var item in toMatchMap) 
      { 
       if (!patternMap.ContainsKey(item.Key) || patternMap[item.Key] < item.Value) 
        return false; 
      } 
      return true; 
     } 
     static void Main(string[] args) 
     { 
      string pattern = "library"; 
      string[] test = { "lib", "rarlib", "rarrlib", "ll" }; 
      foreach (var item in test) 
      { 
       if(Match(pattern, item)) 
        Console.WriteLine("Match item : {0}", item); 
       else 
        Console.WriteLine("Failed item : {0}", item); 
      } 
      Console.ReadKey(); 

      /* 
Match item : lib 
Match item : rarlib 
Failed item : rarrlib 
Failed item : ll 

      */ 
     } 
    } 
} 
+0

Благодарим за то, что вы написали это на удобочитаемом языке! –

0

Я не понимаю, почему вы хотите сделать это с помощью регулярного выражения, когда доступно очень простое и простое решение.

Вы просто посчитаете, сколько раз каждая буква появляется в данном слове, и одним словом вы проверяете. Затем вы проверяете, что каждая буква в тестируемом слове отображается не больше раз, чем в данном слове.

for ch in given_word 
    cnt[ch]++ 
for ch in test_word 
    cnt[ch]-- 
for ch='a'..'z' 
    if cnt[ch]<0 
     answer is no 
if for all leters cnt[ch]>=0 
    answer is yes 
+0

Хорошо, я посмотрю на это. Я вернусь, как только попробую это. Спасибо. –

1

Регулярное выражение не будет работать для этого. Решением будет просто подсчет символов вашего списка.

Например, в JavaScript:

function count(str){ 
 
    return str.split('').reduce(function(m,c){ 
 
    m[c] = (m[c]||0)+1; 
 
    return m; 
 
    },{}) 
 
} 
 
function check(str, reference){ 
 
    var ms = count(str), mr = count(reference); 
 
    for (var k in ms) { 
 
    if (!(ms[k]<=mr[k])) return false; 
 
    } 
 
    return true; 
 
} 
 

 
// what follows is only for demonstration in a snippet 
 
$('button').click(function(){ 
 
    $('#r').text(check($('#a').val(), "library") ? "OK":"NOT OK"); 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<input id=a value="rarlib"> 
 
<button>CHECK</button> 
 
<div id=r></div>

+0

Как и другие ребята, кажется, что так оно и есть. Спасибо за это :) –

Смежные вопросы