Я бы использовал решение, которое выполняет сопоставление путем преобразования в строку ...
Вы должны написать простую функцию, реализующую алгоритм поиска Knuth-Morris-Pratt . Это будет самый быстрый простой алгоритм, который вы можете использовать для поиска правильных индексов. (Вы можете использовать Boyer-Moore , но для этого потребуется больше настроек.
После того как вы оптимизировали алгоритм , вы можете попытаться найти другие виды оптимизации. Но вы должны начать с основ.
Например, текущим «самым быстрым» является решение Locate от Jb Evian.
если вы посмотрите на ядро
for (int i = 0; i < self.Length; i++) {
if (!IsMatch (self, i, candidate))
continue;
list.Add (i);
}
. После соответствия под алгоритма он начнет находить совпадение в i + 1, но вы уже знаете, что первым возможным совпадением будет i + кандидат .Length Так что если вы добавите
i += candidate.Length -2; // -2 instead of -1 because the i++ will add the last index
, это будет намного быстрее, если вы ожидаете много вхождений подмножества в надмножество. (Бруно Конде уже делает это в своем решении)
Но это всего лишь половина алгоритма KNP, вы также должны добавить дополнительный параметр к методу IsMatch, называемому numberOfValidMatches, который будет выходным параметром.
это разрешило бы следующее:
int validMatches = 0;
if (!IsMatch (self, i, candidate, out validMatches))
{
i += validMatches - 1; // -1 because the i++ will do the last one
continue;
}
и
static bool IsMatch (byte [] array, int position, byte [] candidate, out int numberOfValidMatches)
{
numberOfValidMatches = 0;
if (candidate.Length > (array.Length - position))
return false;
for (i = 0; i < candidate.Length; i++)
{
if (array [position + i] != candidate [i])
return false;
numberOfValidMatches++;
}
return true;
}
Немного рефакторинга, и вы можете использовать numberOfValidMatches в качестве переменной цикла и переписать цикл Locate с помощью while, чтобы избежать -2 и -1. Но я просто хотел пояснить, как вы могли бы добавить алгоритм KMP.
blockquote>public class Rule : MonoBehaviour{} Rule rule2 = new Rule();
Вы не можете использовать ключевое слово
new
для создания нового экземпляра, если вы наследуете его изMonoBehaviour
.Вы должны получить исключение, говорит :
Вы пытаетесь создать MonoBehaviour, используя ключевое слово 'new'. Это запрещено. MonoBehaviours можно добавлять только с помощью AddComponent (). Кроме того, ваш скрипт может наследовать от ScriptableObject или вообще никакого базового класса
blockquote>. Ваш код работал бы, если у вас
public class Rule {}
, но у вас естьpublic class Rule : MonoBehaviour {}
.Создание нового экземпляра класса, полученного из
MonoBehaviour
:Пример класса:
public class Rule : MonoBehaviour { public Rule(int i) { } }
Если вы наследуете
MonoBehaviour
, вы должны либо используйтеGameObject.AddComponent
илиInstantiate
для создания нового экземпляра.Rule rule2 = null; void Start() { rule2 = gameObject.AddComponent<Rule>(); }
ИЛИ
public Rule rulePrefab; Rule rule2; void Start() { rule2 = Instantiate(rulePrefab) as Rule; }
Если скрипт
Rule
уже существуют и прикреплены к GameObject, вам не нужно создавать / добавлять / создавать новые экземпляры этого сценария. Просто используйте функциюGetComponent
, чтобы получить экземпляр скрипта из GameObject, к которому он присоединен.Rule rule2; void Start() { rule2 = GameObject.Find("NameObjectScriptIsAttachedTo").GetComponent<Rule>(); }
Вы заметите, что вы не можете использовать параметр в конструкторе, когда вы выводите свой скрипт из
MonoBehaviour
.
Создание нового экземпляра класса, который НЕ выводится из
MonoBehaviour
:Пример класса: (Обратите внимание, что он не является результатом "
MonoBehaviour
"public class Rule { public Rule(int i) { } }
Если вы не наследуете от
MonoBehaviour
, вы должны использовать ключевое словоnew
для создания нового экземпляра. Теперь вы можете использовать параметр в конструкторе, если вы хотите.Rule rule2 = null; void Start() { rule2 = new Rule(3); }
EDIT:
В последней версии Unity создается новый экземпляр скрипта, который наследует от
MonoBehaviour
с помощьюnew
может не дать вам ошибку и не может бытьnull
слишком , но все функции обратного вызова не будут выполняться . К ним относятся функцииAwake
,Start
,Update
и другие. , вы все равно должны сделать это правильно, как указано в начале этого ответа.
Просто следите за тем, как я это сделал и почему:
Rule
из MonoBehaviour
, чтобы избежать отслеживания создания и удаления объектов gameObjects, которая оказалась болью. Invoke
не существует в родовых классах, я заменил его отражением, как описано здесь здесь
CatchManager
иNet
, которые находятся внутри скриптаRule
– Programmer 23 May 2016 в 20:14