diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 6a6a0a4ee282e5e1cf865edcbfc2eabd520cb701..ab9edb1107539c31ecc84b224b02e14a3c69acf5 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -61,6 +61,8 @@ public class BinaryDictionary extends Dictionary {
     public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING =
             new Flag(R.bool.config_require_umlaut_processing, 0x1);
 
+    public static final Flag FLAG_USE_FULL_EDIT_DISTANCE = new Flag(0x2);
+
     // Can create a new flag from extravalue :
     // public static final Flag FLAG_MYFLAG =
     //         new Flag("my_flag", 0x02);
diff --git a/java/src/com/android/inputmethod/latin/Flag.java b/java/src/com/android/inputmethod/latin/Flag.java
index 3cb8f7e177eee83a61a813fd3090d60f3bd551e5..4ba6c80f59a1b2de9fabd4b078f028fd89838932 100644
--- a/java/src/com/android/inputmethod/latin/Flag.java
+++ b/java/src/com/android/inputmethod/latin/Flag.java
@@ -25,8 +25,9 @@ public class Flag {
     public final int mMask;
     public final int mSource;
 
-    static private final int SOURCE_CONFIG = 1;
-    static private final int SOURCE_EXTRAVALUE = 2;
+    private static final int SOURCE_CONFIG = 1;
+    private static final int SOURCE_EXTRAVALUE = 2;
+    private static final int SOURCE_PARAM = 3;
 
     public Flag(int resourceId, int mask) {
         mName = null;
@@ -42,6 +43,13 @@ public class Flag {
         mMask = mask;
     }
 
+    public Flag(int mask) {
+        mName = null;
+        mResource = 0;
+        mSource = SOURCE_PARAM;
+        mMask = mask;
+    }
+
     // If context/switcher are null, set all related flags in flagArray to on.
     public static int initFlags(Flag[] flagArray, Context context, SubtypeSwitcher switcher) {
         int flags = 0;
@@ -57,6 +65,9 @@ public class Flag {
                             switcher.currentSubtypeContainsExtraValueKey(entry.mName))
                         flags |= entry.mMask;
                     break;
+                case Flag.SOURCE_PARAM:
+                    flags |= entry.mMask;
+                    break;
             }
         }
         return flags;
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index d5bfed017f34a5a3ff49d887dd00d44720f531aa..9a7e5f35da5b4ddeb740e8ade5e862c269220f09 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -62,7 +62,8 @@ void Correction::initCorrectionState(
 }
 
 void Correction::setCorrectionParams(const int skipPos, const int excessivePos,
-        const int transposedPos, const int spaceProximityPos, const int missingSpacePos) {
+        const int transposedPos, const int spaceProximityPos, const int missingSpacePos,
+        const bool useFullEditDistance) {
     // TODO: remove
     mTransposedPos = transposedPos;
     mExcessivePos = excessivePos;
@@ -74,6 +75,7 @@ void Correction::setCorrectionParams(const int skipPos, const int excessivePos,
 
     mSpaceProximityPos = spaceProximityPos;
     mMissingSpacePos = missingSpacePos;
+    mUseFullEditDistance = useFullEditDistance;
 }
 
 void Correction::checkState() {
@@ -439,7 +441,7 @@ inline static void multiplyIntCapped(const int multiplier, int *base) {
 }
 
 inline static int powerIntCapped(const int base, const int n) {
-    if (n == 0) return 1;
+    if (n <= 0) return 1;
     if (base == 2) {
         return n < 31 ? 1 << n : S_INT_MAX;
     } else {
@@ -529,6 +531,8 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
     const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
     const int proximityMatchedCount = correction->mProximityCount;
     const bool lastCharExceeded = correction->mLastCharExceeded;
+    const bool useFullEditDistance = correction->mUseFullEditDistance;
+    const int outputLength = outputIndex + 1;
     if (skippedCount >= inputLength || inputLength == 0) {
         return -1;
     }
@@ -682,6 +686,12 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
         multiplyIntCapped(fullWordMultiplier, &finalFreq);
     }
 
+    if (useFullEditDistance && outputLength > inputLength + 1) {
+        const int diff = outputLength - inputLength - 1;
+        const int divider = diff < 31 ? 1 << diff : S_INT_MAX;
+        finalFreq = divider > finalFreq ? 1 : finalFreq / divider;
+    }
+
     if (DEBUG_DICT_FULL) {
         LOGI("calc: %d, %d", outputIndex, sameLength);
     }
diff --git a/native/src/correction.h b/native/src/correction.h
index 41130ad77ae98a684e4ad075fa5e6fc1f3ff12ff..ddb98b9d8464ca30f9d4028aef6fbf9d97c630e6 100644
--- a/native/src/correction.h
+++ b/native/src/correction.h
@@ -44,7 +44,7 @@ public:
 
     // TODO: remove
     void setCorrectionParams(const int skipPos, const int excessivePos, const int transposedPos,
-            const int spaceProximityPos, const int missingSpacePos);
+            const int spaceProximityPos, const int missingSpacePos, const bool useFullEditDistance);
     void checkState();
     bool initProcessState(const int index);
 
@@ -111,6 +111,7 @@ private:
     const int FULL_WORD_MULTIPLIER;
     const ProximityInfo *mProximityInfo;
 
+    bool mUseFullEditDistance;
     int mMaxEditDistance;
     int mMaxDepth;
     int mInputLength;
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 517dc843e73462a071747e715d82e96decb79953..1b798a8f17d106aa10ff889ac3c4c617c177fc9b 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -132,7 +132,8 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit
         memcpy(codesDest, codesSrc, remainingBytes);
 
     getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codesBuffer,
-            (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS + codesRemain, outWords, frequencies);
+            (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS + codesRemain, outWords, frequencies,
+            flags);
 }
 
 int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
@@ -146,7 +147,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x
                 codesSize, flags, codes, codesSize, 0, codesBuffer, outWords, frequencies);
     } else { // Normal processing
         getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize,
-                outWords, frequencies);
+                outWords, frequencies, flags);
     }
 
     PROF_START(20);
@@ -175,7 +176,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x
 
 void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
         const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize,
-        unsigned short *outWords, int *frequencies) {
+        unsigned short *outWords, int *frequencies, const int flags) {
 
     PROF_OPEN;
     PROF_START(0);
@@ -187,9 +188,10 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
     mCorrection->initCorrection(mProximityInfo, mInputLength, maxDepth);
     PROF_END(0);
 
+    const bool useFullEditDistance = USE_FULL_EDIT_DISTANCE & flags;
     // TODO: remove
     PROF_START(1);
-    getSuggestionCandidates();
+    getSuggestionCandidates(useFullEditDistance);
     PROF_END(1);
 
     PROF_START(2);
@@ -212,7 +214,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
             if (DEBUG_DICT) {
                 LOGI("--- Suggest missing space characters %d", i);
             }
-            getMissingSpaceWords(mInputLength, i, mCorrection);
+            getMissingSpaceWords(mInputLength, i, mCorrection, useFullEditDistance);
         }
     }
     PROF_END(5);
@@ -231,7 +233,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
                         i, x, y, proximityInfo->hasSpaceProximity(x, y));
             }
             if (proximityInfo->hasSpaceProximity(x, y)) {
-                getMistypedSpaceWords(mInputLength, i, mCorrection);
+                getMistypedSpaceWords(mInputLength, i, mCorrection, useFullEditDistance);
             }
         }
     }
@@ -315,10 +317,10 @@ bool UnigramDictionary::addWord(unsigned short *word, int length, int frequency)
 static const char QUOTE = '\'';
 static const char SPACE = ' ';
 
-void UnigramDictionary::getSuggestionCandidates() {
+void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance) {
     // TODO: Remove setCorrectionParams
     mCorrection->setCorrectionParams(0, 0, 0,
-            -1 /* spaceProximityPos */, -1 /* missingSpacePos */);
+            -1 /* spaceProximityPos */, -1 /* missingSpacePos */, useFullEditDistance);
     int rootPosition = ROOT_POS;
     // Get the number of children of root, then increment the position
     int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition);
@@ -349,16 +351,20 @@ void UnigramDictionary::getSuggestionCandidates() {
 }
 
 void UnigramDictionary::getMissingSpaceWords(
-        const int inputLength, const int missingSpacePos, Correction *correction) {
+        const int inputLength, const int missingSpacePos, Correction *correction,
+        const bool useFullEditDistance) {
     correction->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */,
-            -1 /* transposedPos */, -1 /* spaceProximityPos */, missingSpacePos);
+            -1 /* transposedPos */, -1 /* spaceProximityPos */, missingSpacePos,
+            useFullEditDistance);
     getSplitTwoWordsSuggestion(inputLength, correction);
 }
 
 void UnigramDictionary::getMistypedSpaceWords(
-        const int inputLength, const int spaceProximityPos, Correction *correction) {
+        const int inputLength, const int spaceProximityPos, Correction *correction,
+        const bool useFullEditDistance) {
     correction->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */,
-            -1 /* transposedPos */, spaceProximityPos, -1 /* missingSpacePos */);
+            -1 /* transposedPos */, spaceProximityPos, -1 /* missingSpacePos */,
+            useFullEditDistance);
     getSplitTwoWordsSuggestion(inputLength, correction);
 }
 
diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h
index 65746db8d3bba980a049a9c9429c79e2327e8011..ef9709a89a579edfa05a1565d9564de661a230c7 100644
--- a/native/src/unigram_dictionary.h
+++ b/native/src/unigram_dictionary.h
@@ -78,7 +78,7 @@ private:
 
     void getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
             const int *ycoordinates, const int *codes, const int codesSize,
-            unsigned short *outWords, int *frequencies);
+            unsigned short *outWords, int *frequencies, const int flags);
     bool isDigraph(const int* codes, const int i, const int codesSize) const;
     void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo,
         const int *xcoordinates, const int* ycoordinates, const int *codesBuffer,
@@ -87,13 +87,13 @@ private:
     void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
             const int *ycoordinates, const int *codes, const int codesSize,
             unsigned short *outWords, int *frequencies);
-    void getSuggestionCandidates();
+    void getSuggestionCandidates(const bool useFullEditDistance);
     bool addWord(unsigned short *word, int length, int frequency);
     void getSplitTwoWordsSuggestion(const int inputLength, Correction *correction);
-    void getMissingSpaceWords(
-            const int inputLength, const int missingSpacePos, Correction *correction);
-    void getMistypedSpaceWords(
-            const int inputLength, const int spaceProximityPos, Correction *correction);
+    void getMissingSpaceWords(const int inputLength, const int missingSpacePos,
+            Correction *correction, const bool useFullEditDistance);
+    void getMistypedSpaceWords(const int inputLength, const int spaceProximityPos,
+            Correction *correction, const bool useFullEditDistance);
     void onTerminal(const int freq, Correction *correction);
     bool needsToSkipCurrentNode(const unsigned short c,
             const int inputIndex, const int skipPos, const int depth);
@@ -122,7 +122,8 @@ private:
     // or something very bad (like, the apocalypse) will happen.
     // Please update both at the same time.
     enum {
-        REQUIRES_GERMAN_UMLAUT_PROCESSING = 0x1
+        REQUIRES_GERMAN_UMLAUT_PROCESSING = 0x1,
+        USE_FULL_EDIT_DISTANCE = 0x2
     };
     static const struct digraph_t { int first; int second; } GERMAN_UMLAUT_DIGRAPHS[];