Merge "Remove country name from space bar text when appropriate"
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index afb32d1..c1372bd 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -34,9 +34,6 @@
 # To suppress compiler warnings for unused variables/functions used for debug features etc.
 LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function
 
-# For C++11
-LOCAL_CFLAGS += -std=c++11
-
 include $(LOCAL_PATH)/NativeFileList.mk
 
 LOCAL_SRC_FILES := \
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.cpp b/native/jni/src/suggest/core/dicnode/dic_node.cpp
index 7385597..414dc3b 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node.cpp
@@ -24,8 +24,7 @@
           mProfiler(dicNode.mProfiler),
 #endif
           mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState),
-          mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion), mIsUsed(dicNode.mIsUsed),
-          mReleaseListener(nullptr) {
+          mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion) {
     /* empty */
 }
 
@@ -36,8 +35,6 @@
     mDicNodeProperties = dicNode.mDicNodeProperties;
     mDicNodeState = dicNode.mDicNodeState;
     mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion;
-    mIsUsed = dicNode.mIsUsed;
-    mReleaseListener = dicNode.mReleaseListener;
     return *this;
 }
 
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 258aa9c..47f5ec0 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -19,7 +19,6 @@
 
 #include "defines.h"
 #include "suggest/core/dicnode/dic_node_profiler.h"
-#include "suggest/core/dicnode/dic_node_release_listener.h"
 #include "suggest/core/dicnode/dic_node_utils.h"
 #include "suggest/core/dicnode/internal/dic_node_state.h"
 #include "suggest/core/dicnode/internal/dic_node_properties.h"
@@ -45,7 +44,8 @@
                             + mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(), \
                     charBuf, NELEMS(charBuf)); \
             AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %d, %5f,", header, \
-                    getSpatialDistanceForScoring(), getLanguageDistanceForScoring(), \
+                    getSpatialDistanceForScoring(), \
+                    mDicNodeState.mDicNodeStateScoring.getLanguageDistance(), \
                     getNormalizedCompoundDistance(), getRawLength(), charBuf, \
                     getInputIndex(0), getNormalizedCompoundDistanceAfterFirstWord()); \
         } while (0)
@@ -89,8 +89,7 @@
 #if DEBUG_DICT
               mProfiler(),
 #endif
-              mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false),
-              mIsUsed(false), mReleaseListener(nullptr) {}
+              mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false) {}
 
     DicNode(const DicNode &dicNode);
     DicNode &operator=(const DicNode &dicNode);
@@ -98,7 +97,6 @@
 
     // Init for copy
     void initByCopy(const DicNode *const dicNode) {
-        mIsUsed = true;
         mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
         mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties);
         mDicNodeState.initByCopy(&dicNode->mDicNodeState);
@@ -107,7 +105,6 @@
 
     // Init for root with prevWordPtNodePos which is used for bigram
     void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) {
-        mIsUsed = true;
         mIsCachedForNextSuggestion = false;
         mDicNodeProperties.init(rootPtNodeArrayPos, prevWordPtNodePos);
         mDicNodeState.init();
@@ -116,7 +113,6 @@
 
     // Init for root with previous word
     void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
-        mIsUsed = true;
         mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
         mDicNodeProperties.init(rootPtNodeArrayPos, dicNode->mDicNodeProperties.getPtNodePos());
         mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
@@ -125,10 +121,11 @@
     }
 
     void initAsPassingChild(DicNode *parentDicNode) {
-        mIsUsed = true;
         mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
-        const int parentCodePoint = parentDicNode->getNodeTypedCodePoint();
-        mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint);
+        const int codePoint =
+                parentDicNode->mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(
+                            parentDicNode->getNodeCodePointCount());
+        mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, codePoint);
         mDicNodeState.initByCopy(&parentDicNode->mDicNodeState);
         PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler);
     }
@@ -137,7 +134,6 @@
             const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
             const bool hasChildren, const bool isBlacklistedOrNotAWord,
             const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
-        mIsUsed = true;
         uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
         mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
         const uint16_t newLeavingDepth = static_cast<uint16_t>(
@@ -150,17 +146,6 @@
         PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
     }
 
-    AK_FORCE_INLINE void finalize() {
-        mIsUsed = false;
-        if (mReleaseListener) {
-            mReleaseListener->onReleased(this);
-        }
-    }
-
-    bool isUsed() const {
-        return mIsUsed;
-    }
-
     bool isRoot() const {
         return getNodeCodePointCount() == 0;
     }
@@ -186,11 +171,6 @@
         mIsCachedForNextSuggestion = true;
     }
 
-    // Used to expand the node in DicNodeUtils
-    int getNodeTypedCodePoint() const {
-        return mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(getNodeCodePointCount());
-    }
-
     // Check if the current word and the previous word can be considered as a valid multiple word
     // suggestion.
     bool isValidMultipleWordSuggestion() const {
@@ -261,17 +241,13 @@
     }
 
     bool isTotalInputSizeExceedingLimit() const {
-        const int prevWordsLen = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength();
-        const int currentWordDepth = getNodeCodePointCount();
         // TODO: 3 can be 2? Needs to be investigated.
         // TODO: Have a const variable for 3 (or 2)
-        return prevWordsLen + currentWordDepth > MAX_WORD_LENGTH - 3;
+        return getTotalNodeCodePointCount() > MAX_WORD_LENGTH - 3;
     }
 
     void outputResult(int *dest) const {
-        const uint16_t prevWordLength = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength();
-        const uint16_t currentDepth = getNodeCodePointCount();
-        memmove(dest, getOutputWordBuf(), (prevWordLength + currentDepth) * sizeof(dest[0]));
+        memmove(dest, getOutputWordBuf(), getTotalNodeCodePointCount() * sizeof(dest[0]));
         DUMP_WORD_AND_SCORE("OUTPUT");
     }
 
@@ -329,11 +305,6 @@
         return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight);
     }
 
-    // Used to commit input partially
-    int getPrevWordPtNodePos() const {
-        return mDicNodeProperties.getPrevWordTerminalPtNodePos();
-    }
-
     AK_FORCE_INLINE const int *getOutputWordBuf() const {
         return mDicNodeState.mDicNodeStateOutput.getCodePointBuf();
     }
@@ -396,10 +367,6 @@
         return mDicNodeState.mDicNodeStateScoring.getSpatialDistance();
     }
 
-    float getLanguageDistanceForScoring() const {
-        return mDicNodeState.mDicNodeStateScoring.getLanguageDistance();
-    }
-
     // For space-aware gestures, we store the normalized distance at the char index
     // that ends the first word of the suggestion. We call this the distance after
     // first word.
@@ -407,22 +374,10 @@
         return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistanceAfterFirstWord();
     }
 
-    float getLanguageDistanceRatePerWordForScoring() const {
-        const float langDist = getLanguageDistanceForScoring();
-        const float totalWordCount =
-                static_cast<float>(mDicNodeState.mDicNodeStateOutput.getPrevWordCount() + 1);
-        return langDist / totalWordCount;
-    }
-
     float getRawLength() const {
         return mDicNodeState.mDicNodeStateScoring.getRawLength();
     }
 
-    bool isLessThanOneErrorForScoring() const {
-        return mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount()
-                + mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount() <= 1;
-    }
-
     DoubleLetterLevel getDoubleLetterLevel() const {
         return mDicNodeState.mDicNodeStateScoring.getDoubleLetterLevel();
     }
@@ -466,10 +421,6 @@
 #endif
     }
 
-    void setReleaseListener(DicNodeReleaseListener *releaseListener) {
-        mReleaseListener = releaseListener;
-    }
-
     AK_FORCE_INLINE bool compare(const DicNode *right) const {
         // Promote exact matches to prevent them from being pruned.
         const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes());
@@ -507,8 +458,6 @@
     DicNodeState mDicNodeState;
     // TODO: Remove
     bool mIsCachedForNextSuggestion;
-    bool mIsUsed;
-    DicNodeReleaseListener *mReleaseListener;
 
     AK_FORCE_INLINE int getTotalInputIndex() const {
         int index = 0;
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_pool.h b/native/jni/src/suggest/core/dicnode/dic_node_pool.h
new file mode 100644
index 0000000..a660b74
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_pool.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_NODE_POOL_H
+#define LATINIME_DIC_NODE_POOL_H
+
+#include <deque>
+#include <unordered_set>
+#include <vector>
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node.h"
+
+namespace latinime {
+
+class DicNodePool {
+ public:
+    explicit DicNodePool(const int capacity) : mDicNodes(), mPooledDicNodes() {
+        reset(capacity);
+    }
+
+    void reset(const int capacity) {
+        if (capacity == static_cast<int>(mDicNodes.size())
+                && capacity == static_cast<int>(mPooledDicNodes.size())) {
+            // No need to reset.
+            return;
+        }
+        mDicNodes.resize(capacity);
+        mDicNodes.shrink_to_fit();
+        mPooledDicNodes.clear();
+        for (auto &dicNode : mDicNodes) {
+            mPooledDicNodes.emplace_back(&dicNode);
+        }
+    }
+
+    // Get a DicNode instance from the pool. The instance has to be returned by returnInstance().
+    DicNode *getInstance() {
+        if (mPooledDicNodes.empty()) {
+            return nullptr;
+        }
+        DicNode *const dicNode = mPooledDicNodes.back();
+        mPooledDicNodes.pop_back();
+        return dicNode;
+    }
+
+    // Return an instance that has been removed from the pool by getInstance() to the pool. The
+    // instance must not be used after returning without getInstance().
+    void placeBackInstance(DicNode *dicNode) {
+        mPooledDicNodes.emplace_back(dicNode);
+    }
+
+    void dump() const {
+        AKLOGI("\n\n\n\n\n===========================");
+        std::unordered_set<const DicNode*> usedDicNodes;
+        for (const auto &dicNode : mDicNodes) {
+            usedDicNodes.insert(&dicNode);
+        }
+        for (const auto &dicNodePtr : mPooledDicNodes) {
+            usedDicNodes.erase(dicNodePtr);
+        }
+        for (const auto &usedDicNodePtr : usedDicNodes) {
+            usedDicNodePtr->dump("DIC_NODE_POOL: ");
+        }
+        AKLOGI("===========================\n\n\n\n\n");
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePool);
+
+    std::vector<DicNode> mDicNodes;
+    std::deque<DicNode*> mPooledDicNodes;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_POOL_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
index 213b1b9..7b753f2 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
@@ -23,38 +23,30 @@
 
 #include "defines.h"
 #include "suggest/core/dicnode/dic_node.h"
-#include "suggest/core/dicnode/dic_node_release_listener.h"
+#include "suggest/core/dicnode/dic_node_pool.h"
 
 namespace latinime {
 
-class DicNodePriorityQueue : public DicNodeReleaseListener {
+class DicNodePriorityQueue {
  public:
     AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity)
-            : mCapacity(capacity), mMaxSize(capacity), mDicNodesBuf(),
-              mUnusedNodeIndices(), mNextUnusedNodeId(0), mDicNodesQueue() {
-        mDicNodesBuf.resize(mCapacity + 1);
-        mUnusedNodeIndices.resize(mCapacity + 1);
-        clearAndResizeToCapacity();
+            : mMaxSize(capacity), mDicNodesQueue(), mDicNodePool(capacity) {
+        clear();
     }
 
     // Non virtual inline destructor -- never inherit this class
     AK_FORCE_INLINE ~DicNodePriorityQueue() {}
 
-    int getSize() const {
+    AK_FORCE_INLINE int getSize() const {
         return static_cast<int>(mDicNodesQueue.size());
     }
 
-    int getMaxSize() const {
+    AK_FORCE_INLINE int getMaxSize() const {
         return mMaxSize;
     }
 
     AK_FORCE_INLINE void setMaxSize(const int maxSize) {
-        ASSERT(maxSize <= mCapacity);
-        mMaxSize = std::min(maxSize, mCapacity);
-    }
-
-    AK_FORCE_INLINE void clearAndResizeToCapacity() {
-        clearAndResize(mCapacity);
+        mMaxSize = maxSize;
     }
 
     AK_FORCE_INLINE void clear() {
@@ -62,25 +54,32 @@
     }
 
     AK_FORCE_INLINE void clearAndResize(const int maxSize) {
-        ASSERT(maxSize <= mCapacity);
+        mMaxSize = maxSize;
         while (!mDicNodesQueue.empty()) {
             mDicNodesQueue.pop();
         }
-        setMaxSize(maxSize);
-        for (int i = 0; i < mCapacity + 1; ++i) {
-            mDicNodesBuf[i].finalize();
-            mDicNodesBuf[i].setReleaseListener(this);
-            mUnusedNodeIndices[i] = (i == mCapacity) ? NOT_A_NODE_ID : (i + 1);
+        mDicNodePool.reset(mMaxSize + 1);
+    }
+
+    AK_FORCE_INLINE void copyPush(const DicNode *const dicNode) {
+        DicNode *const pooledDicNode = newDicNode(dicNode);
+        if (!pooledDicNode) {
+            return;
         }
-        mNextUnusedNodeId = 0;
+        if (getSize() < mMaxSize) {
+            mDicNodesQueue.push(pooledDicNode);
+            return;
+        }
+        if (betterThanWorstDicNode(pooledDicNode)) {
+            mDicNodePool.placeBackInstance(mDicNodesQueue.top());
+            mDicNodesQueue.pop();
+            mDicNodesQueue.push(pooledDicNode);
+            return;
+        }
+        mDicNodePool.placeBackInstance(pooledDicNode);
     }
 
-    // Copy
-    AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode) {
-        return copyPush(dicNode, mMaxSize);
-    }
-
-    AK_FORCE_INLINE void copyPop(DicNode *dest) {
+    AK_FORCE_INLINE void copyPop(DicNode *const dest) {
         if (mDicNodesQueue.empty()) {
             ASSERT(false);
             return;
@@ -89,34 +88,16 @@
         if (dest) {
             DicNodeUtils::initByCopy(node, dest);
         }
-        node->finalize();
+        mDicNodePool.placeBackInstance(node);
         mDicNodesQueue.pop();
     }
 
-    void onReleased(const DicNode *dicNode) {
-        const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
-        if (mUnusedNodeIndices[index] != NOT_A_NODE_ID) {
-            // it's already released
-            return;
-        }
-        mUnusedNodeIndices[index] = mNextUnusedNodeId;
-        mNextUnusedNodeId = index;
-        ASSERT(index >= 0 && index < (mCapacity + 1));
-    }
-
-    AK_FORCE_INLINE void dump() const {
-        AKLOGI("\n\n\n\n\n===========================");
-        for (int i = 0; i < mCapacity + 1; ++i) {
-            if (mDicNodesBuf[i].isUsed()) {
-                mDicNodesBuf[i].dump("QUEUE: ");
-            }
-        }
-        AKLOGI("===========================\n\n\n\n\n");
+    AK_FORCE_INLINE void dump() {
+        mDicNodePool.dump();
     }
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue);
-    static const int NOT_A_NODE_ID = -1;
 
     AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left,
             const DicNode *const right) {
@@ -124,26 +105,15 @@
     }
 
     struct DicNodeComparator {
-        bool operator ()(DicNode *left, DicNode *right) {
+        bool operator ()(const DicNode *left, const DicNode *right) const {
             return compareDicNode(left, right);
         }
     };
 
     typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
-    const int mCapacity;
     int mMaxSize;
-    std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
-    std::vector<int> mUnusedNodeIndices;
-    int mNextUnusedNodeId;
     DicNodesQueue mDicNodesQueue;
-
-    inline bool isFull(const int maxSize) const {
-        return getSize() >= maxSize;
-    }
-
-    AK_FORCE_INLINE void pop() {
-        copyPop(nullptr);
-    }
+    DicNodePool mDicNodePool;
 
     AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const {
         DicNode *worstNode = mDicNodesQueue.top();
@@ -153,61 +123,13 @@
         return compareDicNode(dicNode, worstNode);
     }
 
-    AK_FORCE_INLINE DicNode *searchEmptyDicNode() {
-        if (mCapacity == 0) {
-            return nullptr;
-        }
-        if (mNextUnusedNodeId == NOT_A_NODE_ID) {
-            AKLOGI("No unused node found.");
-            for (int i = 0; i < mCapacity + 1; ++i) {
-                AKLOGI("Dump node availability, %d, %d, %d",
-                        i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]);
-            }
-            ASSERT(false);
-            return nullptr;
-        }
-        DicNode *dicNode = &mDicNodesBuf[mNextUnusedNodeId];
-        markNodeAsUsed(dicNode);
-        return dicNode;
-    }
-
-    AK_FORCE_INLINE void markNodeAsUsed(DicNode *dicNode) {
-        const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
-        mNextUnusedNodeId = mUnusedNodeIndices[index];
-        mUnusedNodeIndices[index] = NOT_A_NODE_ID;
-        ASSERT(index >= 0 && index < (mCapacity + 1));
-    }
-
-    AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) {
-        if (!dicNode) {
-            return nullptr;
-        }
-        if (!isFull(maxSize)) {
-            mDicNodesQueue.push(dicNode);
-            return dicNode;
-        }
-        if (betterThanWorstDicNode(dicNode)) {
-            pop();
-            mDicNodesQueue.push(dicNode);
-            return dicNode;
-        }
-        dicNode->finalize();
-        return nullptr;
-    }
-
-    // Copy
-    AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode, const int maxSize) {
-        return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize);
-    }
-
     AK_FORCE_INLINE DicNode *newDicNode(const DicNode *const dicNode) {
-        DicNode *newNode = searchEmptyDicNode();
+        DicNode *newNode = mDicNodePool.getInstance();
         if (newNode) {
             DicNodeUtils::initByCopy(dicNode, newNode);
         }
         return newNode;
     }
-
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
deleted file mode 100644
index c3f4329..0000000
--- a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LATINIME_DIC_NODE_RELEASE_LISTENER_H
-#define LATINIME_DIC_NODE_RELEASE_LISTENER_H
-
-#include "defines.h"
-
-namespace latinime {
-
-class DicNode;
-
-class DicNodeReleaseListener {
- public:
-    DicNodeReleaseListener() {}
-    virtual ~DicNodeReleaseListener() {}
-    virtual void onReleased(const DicNode *dicNode) = 0;
- private:
-    DISALLOW_COPY_AND_ASSIGN(DicNodeReleaseListener);
-};
-} // namespace latinime
-#endif // LATINIME_DIC_NODE_RELEASE_LISTENER_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
index 6b8dc8c..089d446 100644
--- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
@@ -49,15 +49,14 @@
     AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
         mInputIndex = 0;
         mLastCachedInputIndex = 0;
-        // We want to use the max capacity for the current active dic node queue.
-        mActiveDicNodes->clearAndResizeToCapacity();
-        // nextActiveSize is used to limit the next iteration's active dic node size.
+        // The size of current active DicNode queue doesn't have to be changed.
+        mActiveDicNodes->clear();
+        // nextActiveSize is used to limit the next iteration's active DicNode size.
         const int nextActiveSizeFittingToTheCapacity = std::min(nextActiveSize, getCacheCapacity());
         mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity);
         mTerminalDicNodes->clearAndResize(terminalSize);
-        // We want to use the max capacity for the cached dic nodes that will be used for the
-        // continuous suggestion.
-        mCachedDicNodesForContinuousSuggestion->clearAndResizeToCapacity();
+        // The size of cached DicNode queue doesn't have to be changed.
+        mCachedDicNodesForContinuousSuggestion->clear();
     }
 
     AK_FORCE_INLINE void continueSearch() {
@@ -95,8 +94,8 @@
         mActiveDicNodes->copyPush(dicNode);
     }
 
-    AK_FORCE_INLINE bool copyPushContinue(DicNode *dicNode) {
-        return mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
+    AK_FORCE_INLINE void copyPushContinue(DicNode *dicNode) {
+        mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
     }
 
     AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) {
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
index 7b33206..c4c5716 100644
--- a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
@@ -37,8 +37,8 @@
 const float ScoringParams::PROXIMITY_COST = 0.0694f;
 const float ScoringParams::FIRST_CHAR_PROXIMITY_COST = 0.072f;
 const float ScoringParams::FIRST_PROXIMITY_COST = 0.07788f;
-const float ScoringParams::OMISSION_COST = 0.4676f;
-const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.399f;
+const float ScoringParams::OMISSION_COST = 0.467f;
+const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.345f;
 const float ScoringParams::OMISSION_COST_FIRST_CHAR = 0.5256f;
 const float ScoringParams::INSERTION_COST = 0.7248f;
 const float ScoringParams::TERMINAL_INSERTION_COST = 0.8128f;
@@ -46,18 +46,18 @@
 const float ScoringParams::INSERTION_COST_PROXIMITY_CHAR = 0.674f;
 const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.639f;
 const float ScoringParams::TRANSPOSITION_COST = 0.5608f;
-const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.339f;
+const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.334f;
 const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.4576f;
 const float ScoringParams::SUBSTITUTION_COST = 0.3806f;
-const float ScoringParams::COST_NEW_WORD = 0.0312f;
+const float ScoringParams::COST_NEW_WORD = 0.0314f;
 const float ScoringParams::COST_SECOND_OR_LATER_WORD_FIRST_CHAR_UPPERCASE = 0.3224f;
 const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.1214f;
 const float ScoringParams::COST_FIRST_LOOKAHEAD = 0.4836f;
 const float ScoringParams::COST_LOOKAHEAD = 0.00624f;
-const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.06836f;
+const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.0683f;
 const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.0362f;
 const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.4182f;
 const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f;
 const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f;
-const float ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT = 0.045f;
+const float ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT = 0.095f;
 } // namespace latinime