From cf7e9815187cbdea6a26519f089cda4957d6cf68 Mon Sep 17 00:00:00 2001 From: rikim Date: Sat, 16 May 2020 20:43:55 +0900 Subject: [PATCH 01/21] Add empty TextSearch and Text case to verify --- .../java/com/company/text/TextSearch.java | 13 ++++++++++++ .../java/com/company/text/TextSearchTest.java | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/com/company/text/TextSearch.java create mode 100644 src/test/java/com/company/text/TextSearchTest.java diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java new file mode 100644 index 0000000..a1e919b --- /dev/null +++ b/src/main/java/com/company/text/TextSearch.java @@ -0,0 +1,13 @@ +package com.company.text; + +public class TextSearch { + private final String text; + + public TextSearch(String text) { + this.text = text; + } + + public int searchText(String textToSearch) { + return 0; + } +} diff --git a/src/test/java/com/company/text/TextSearchTest.java b/src/test/java/com/company/text/TextSearchTest.java new file mode 100644 index 0000000..7d8cf0b --- /dev/null +++ b/src/test/java/com/company/text/TextSearchTest.java @@ -0,0 +1,20 @@ +package com.company.text; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TextSearchTest { + @Test + public void searchText_whenSearchingAVAInAVAVA_thenReturning2() { + // Given + String textToSearch = "ava"; + TextSearch avava = new TextSearch("avava"); + + // When + int count = avava.searchText(textToSearch); + + // Then + assertThat(count).isEqualTo(2); + } +} \ No newline at end of file From c996a721600539b81d299bcaf14346759986b699 Mon Sep 17 00:00:00 2001 From: rikim Date: Sat, 16 May 2020 21:04:39 +0900 Subject: [PATCH 02/21] Solve the problem with O(N^2) --- src/main/java/com/company/text/TextSearch.java | 17 ++++++++++++++++- .../java/com/company/text/TextSearchTest.java | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index a1e919b..16bbb5b 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -8,6 +8,21 @@ public TextSearch(String text) { } public int searchText(String textToSearch) { - return 0; + int count = 0; + for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; startIndex++) { + int matchedCharCount = 0; + for (int currIndex = 0; currIndex < textToSearch.length(); currIndex++) { + char ch1 = text.charAt(currIndex + startIndex); + char ch2 = textToSearch.charAt(currIndex); + if (ch1 != ch2) { + break; + } + matchedCharCount++; + } + if (matchedCharCount == textToSearch.length()) { + count++; + } + } + return count; } } diff --git a/src/test/java/com/company/text/TextSearchTest.java b/src/test/java/com/company/text/TextSearchTest.java index 7d8cf0b..175ff3f 100644 --- a/src/test/java/com/company/text/TextSearchTest.java +++ b/src/test/java/com/company/text/TextSearchTest.java @@ -4,7 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class TextSearchTest { +public class TextSearchTest { @Test public void searchText_whenSearchingAVAInAVAVA_thenReturning2() { // Given From b62b6fd5f32e192fb2b66b867b25331e1b189d78 Mon Sep 17 00:00:00 2001 From: rikim Date: Sat, 16 May 2020 21:10:03 +0900 Subject: [PATCH 03/21] Move incrementing currentIndex into for statement --- src/main/java/com/company/text/TextSearch.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 16bbb5b..1ee595a 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -11,13 +11,14 @@ public int searchText(String textToSearch) { int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; startIndex++) { int matchedCharCount = 0; - for (int currIndex = 0; currIndex < textToSearch.length(); currIndex++) { + for (int currIndex = 0; currIndex < textToSearch.length(); ) { char ch1 = text.charAt(currIndex + startIndex); char ch2 = textToSearch.charAt(currIndex); if (ch1 != ch2) { break; } matchedCharCount++; + currIndex++; } if (matchedCharCount == textToSearch.length()) { count++; From 86c5c1d448b9ff188f3b6d88921d63a8fad05f7b Mon Sep 17 00:00:00 2001 From: rikim Date: Sat, 16 May 2020 22:13:01 +0900 Subject: [PATCH 04/21] Move startIndex inside for-loop --- src/main/java/com/company/text/TextSearch.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 1ee595a..6aba5b3 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -9,7 +9,7 @@ public TextSearch(String text) { public int searchText(String textToSearch) { int count = 0; - for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; startIndex++) { + for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; for (int currIndex = 0; currIndex < textToSearch.length(); ) { char ch1 = text.charAt(currIndex + startIndex); @@ -23,6 +23,7 @@ public int searchText(String textToSearch) { if (matchedCharCount == textToSearch.length()) { count++; } + startIndex++; } return count; } From f6de4d4a7ec6bf39d31333de5c1fa8498434204c Mon Sep 17 00:00:00 2001 From: rikim Date: Sat, 16 May 2020 22:15:12 +0900 Subject: [PATCH 05/21] Change char compare order to desc from asc --- src/main/java/com/company/text/TextSearch.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 6aba5b3..85739c2 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -11,14 +11,14 @@ public int searchText(String textToSearch) { int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; - for (int currIndex = 0; currIndex < textToSearch.length(); ) { + for (int currIndex = textToSearch.length() - 1; currIndex >= 0; ) { char ch1 = text.charAt(currIndex + startIndex); char ch2 = textToSearch.charAt(currIndex); if (ch1 != ch2) { break; } matchedCharCount++; - currIndex++; + currIndex--; } if (matchedCharCount == textToSearch.length()) { count++; From f51c5566641bb475aa0139d141fc323a3d6e265c Mon Sep 17 00:00:00 2001 From: rikim Date: Sat, 16 May 2020 23:45:23 +0900 Subject: [PATCH 06/21] Apply KMP algorithm and build cache with O(N^2) --- .../java/com/company/text/TextSearch.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 85739c2..564ec23 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -1,5 +1,8 @@ package com.company.text; +import java.util.HashMap; +import java.util.Map; + public class TextSearch { private final String text; @@ -8,6 +11,7 @@ public TextSearch(String text) { } public int searchText(String textToSearch) { + Map incrementByMatchedPostfix = buildCache(textToSearch); int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; @@ -23,8 +27,31 @@ public int searchText(String textToSearch) { if (matchedCharCount == textToSearch.length()) { count++; } - startIndex++; + startIndex = startIndex + incrementByMatchedPostfix.get(matchedCharCount); } return count; } + + public Map buildCache(String text) { + Map map = new HashMap<>(); + map.put(0, 1); + map.put(text.length(), 1); + for (int len = 1; len < text.length(); len++) { + int matched = 0; + for (int i = 0; i < len; i++) { + char pre = text.charAt(i); + char post = text.charAt(text.length() - 1 - i); + + if (post == pre) { + matched++; + } + } + if (len == matched) { + map.put(len, text.length() - len); + } else { + map.put(len, 1); + } + } + return map; + } } From fced4c1f4bf9cc46eaf13d924711bb8983a50e14 Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 00:10:01 +0900 Subject: [PATCH 07/21] Revert "Apply KMP algorithm and build cache with O(N^2)" This reverts commit f51c5566 --- .../java/com/company/text/TextSearch.java | 29 +------------------ 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 564ec23..85739c2 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -1,8 +1,5 @@ package com.company.text; -import java.util.HashMap; -import java.util.Map; - public class TextSearch { private final String text; @@ -11,7 +8,6 @@ public TextSearch(String text) { } public int searchText(String textToSearch) { - Map incrementByMatchedPostfix = buildCache(textToSearch); int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; @@ -27,31 +23,8 @@ public int searchText(String textToSearch) { if (matchedCharCount == textToSearch.length()) { count++; } - startIndex = startIndex + incrementByMatchedPostfix.get(matchedCharCount); + startIndex++; } return count; } - - public Map buildCache(String text) { - Map map = new HashMap<>(); - map.put(0, 1); - map.put(text.length(), 1); - for (int len = 1; len < text.length(); len++) { - int matched = 0; - for (int i = 0; i < len; i++) { - char pre = text.charAt(i); - char post = text.charAt(text.length() - 1 - i); - - if (post == pre) { - matched++; - } - } - if (len == matched) { - map.put(len, text.length() - len); - } else { - map.put(len, 1); - } - } - return map; - } } From 26317fbe35860ff76869a7110b6f6448dfcf074a Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 00:10:43 +0900 Subject: [PATCH 08/21] Revert "Change char compare order to desc from asc" This reverts commit f6de4d4a --- src/main/java/com/company/text/TextSearch.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 85739c2..6aba5b3 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -11,14 +11,14 @@ public int searchText(String textToSearch) { int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; - for (int currIndex = textToSearch.length() - 1; currIndex >= 0; ) { + for (int currIndex = 0; currIndex < textToSearch.length(); ) { char ch1 = text.charAt(currIndex + startIndex); char ch2 = textToSearch.charAt(currIndex); if (ch1 != ch2) { break; } matchedCharCount++; - currIndex--; + currIndex++; } if (matchedCharCount == textToSearch.length()) { count++; From 1fc2b29e6bf964c2467e85cfc1d66c34a3cda30e Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 14:29:34 +0900 Subject: [PATCH 09/21] Apply incrementMap when incrementing startIndex in searchText --- .../java/com/company/text/TextSearch.java | 44 +++++++++++++++++- .../java/com/company/text/TextSearchTest.java | 45 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/TextSearch.java index 6aba5b3..094c61f 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/TextSearch.java @@ -1,16 +1,23 @@ package com.company.text; +import java.util.HashMap; +import java.util.Map; + public class TextSearch { - private final String text; + public final String text; + public Map integerIntegerMap; public TextSearch(String text) { this.text = text; } public int searchText(String textToSearch) { + integerIntegerMap = this.buildIncrementMap(textToSearch); + System.out.println("start to search"); int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; + System.out.println("startIndex: " + startIndex); for (int currIndex = 0; currIndex < textToSearch.length(); ) { char ch1 = text.charAt(currIndex + startIndex); char ch2 = textToSearch.charAt(currIndex); @@ -22,9 +29,42 @@ public int searchText(String textToSearch) { } if (matchedCharCount == textToSearch.length()) { count++; + startIndex++; + } else if (matchedCharCount == 0 || matchedCharCount == 1) { + startIndex++; + } else { + startIndex = startIndex + this.integerIntegerMap.get(matchedCharCount); } - startIndex++; } return count; } + + public Map buildIncrementMap(String text) { + HashMap map = new HashMap<>(); + for (int partialLength = 2; partialLength < text.length(); partialLength++) { + String partialString = text.substring(0, partialLength); + int maxLengthToMatch = getMaxLengthMatchingPrefixAndPostfix(partialString); + if (maxLengthToMatch == 0) { + map.put(partialLength, 1); + } else { + map.put(partialLength, partialLength - maxLengthToMatch); + } + } + return map; + } + + private int getMaxLengthMatchingPrefixAndPostfix(String subStr) { + System.out.println("subString: " + subStr); + int maxLength = 0; + for (int prefixLength = 1; prefixLength < subStr.length(); prefixLength++) { + String pre = subStr.substring(0, prefixLength); + String post = subStr.substring(subStr.length() - prefixLength); + System.out.println("pre: " + pre + " post: " + post + " prefixLen: " + prefixLength); + if (pre.equals(post)) { + System.out.println("matched"); + maxLength = prefixLength; + } + } + return maxLength; + } } diff --git a/src/test/java/com/company/text/TextSearchTest.java b/src/test/java/com/company/text/TextSearchTest.java index 175ff3f..4cfac38 100644 --- a/src/test/java/com/company/text/TextSearchTest.java +++ b/src/test/java/com/company/text/TextSearchTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.Test; +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThat; public class TextSearchTest { @@ -17,4 +19,47 @@ public void searchText_whenSearchingAVAInAVAVA_thenReturning2() { // Then assertThat(count).isEqualTo(2); } + + @Test + public void buildIncrementMap_whenAAIsGiven_thenIncrementHasNoElement() { + // Given + String textToSearch = "aa"; + TextSearch avava = new TextSearch("avava"); + + // When + Map aaIncrementMap = avava.buildIncrementMap(textToSearch); + + // Then + assertThat(aaIncrementMap).hasSize(0); + } + + @Test + public void buildIncrementMap_when_ABcAB_IsGiven() { + // Given + String textToSearch = "abcabd"; + TextSearch avava = new TextSearch("avava"); + + // When + Map aaIncrementMap = avava.buildIncrementMap(textToSearch); + + // Then + assertThat(aaIncrementMap).hasSize(4); + assertThat(aaIncrementMap.get(2)).isEqualTo(1); + assertThat(aaIncrementMap.get(3)).isEqualTo(1); + assertThat(aaIncrementMap.get(4)).isEqualTo(3); + assertThat(aaIncrementMap.get(5)).isEqualTo(3); + } + + @Test + public void searchText_when_ABcAB_IsGiven() { + // Given + String textToSearch = "abcabd"; + TextSearch avava = new TextSearch("XXXX" + textToSearch + "XXXX" + textToSearch); + + // When + int matchedCount = avava.searchText(textToSearch); + + // Then + assertThat(matchedCount).isEqualTo(2); + } } \ No newline at end of file From 2a0a405140452704eaa975ca2445acbaa7ac524c Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 14:34:00 +0900 Subject: [PATCH 10/21] Rename class and rename vars in Text cases --- ...{TextSearch.java => SearchableString.java} | 6 ++--- ...rchTest.java => SearchableStringTest.java} | 24 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) rename src/main/java/com/company/text/{TextSearch.java => SearchableString.java} (94%) rename src/test/java/com/company/text/{TextSearchTest.java => SearchableStringTest.java} (58%) diff --git a/src/main/java/com/company/text/TextSearch.java b/src/main/java/com/company/text/SearchableString.java similarity index 94% rename from src/main/java/com/company/text/TextSearch.java rename to src/main/java/com/company/text/SearchableString.java index 094c61f..c0741a8 100644 --- a/src/main/java/com/company/text/TextSearch.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -3,11 +3,11 @@ import java.util.HashMap; import java.util.Map; -public class TextSearch { +public class SearchableString { public final String text; public Map integerIntegerMap; - public TextSearch(String text) { + public SearchableString(String text) { this.text = text; } @@ -39,7 +39,7 @@ public int searchText(String textToSearch) { return count; } - public Map buildIncrementMap(String text) { + Map buildIncrementMap(String text) { HashMap map = new HashMap<>(); for (int partialLength = 2; partialLength < text.length(); partialLength++) { String partialString = text.substring(0, partialLength); diff --git a/src/test/java/com/company/text/TextSearchTest.java b/src/test/java/com/company/text/SearchableStringTest.java similarity index 58% rename from src/test/java/com/company/text/TextSearchTest.java rename to src/test/java/com/company/text/SearchableStringTest.java index 4cfac38..cc422c5 100644 --- a/src/test/java/com/company/text/TextSearchTest.java +++ b/src/test/java/com/company/text/SearchableStringTest.java @@ -6,12 +6,12 @@ import static org.assertj.core.api.Assertions.assertThat; -public class TextSearchTest { +public class SearchableStringTest { @Test public void searchText_whenSearchingAVAInAVAVA_thenReturning2() { // Given String textToSearch = "ava"; - TextSearch avava = new TextSearch("avava"); + SearchableString avava = new SearchableString("avava"); // When int count = avava.searchText(textToSearch); @@ -24,7 +24,7 @@ public void searchText_whenSearchingAVAInAVAVA_thenReturning2() { public void buildIncrementMap_whenAAIsGiven_thenIncrementHasNoElement() { // Given String textToSearch = "aa"; - TextSearch avava = new TextSearch("avava"); + SearchableString avava = new SearchableString("avava"); // When Map aaIncrementMap = avava.buildIncrementMap(textToSearch); @@ -37,27 +37,27 @@ public void buildIncrementMap_whenAAIsGiven_thenIncrementHasNoElement() { public void buildIncrementMap_when_ABcAB_IsGiven() { // Given String textToSearch = "abcabd"; - TextSearch avava = new TextSearch("avava"); + SearchableString searchableString = new SearchableString(""); // When - Map aaIncrementMap = avava.buildIncrementMap(textToSearch); + Map incrementMap = searchableString.buildIncrementMap(textToSearch); // Then - assertThat(aaIncrementMap).hasSize(4); - assertThat(aaIncrementMap.get(2)).isEqualTo(1); - assertThat(aaIncrementMap.get(3)).isEqualTo(1); - assertThat(aaIncrementMap.get(4)).isEqualTo(3); - assertThat(aaIncrementMap.get(5)).isEqualTo(3); + assertThat(incrementMap).hasSize(4); + assertThat(incrementMap.get(2)).isEqualTo(1); + assertThat(incrementMap.get(3)).isEqualTo(1); + assertThat(incrementMap.get(4)).isEqualTo(3); + assertThat(incrementMap.get(5)).isEqualTo(3); } @Test public void searchText_when_ABcAB_IsGiven() { // Given String textToSearch = "abcabd"; - TextSearch avava = new TextSearch("XXXX" + textToSearch + "XXXX" + textToSearch); + SearchableString searchableString = new SearchableString("XXXX" + textToSearch + "XXXX" + textToSearch); // When - int matchedCount = avava.searchText(textToSearch); + int matchedCount = searchableString.searchText(textToSearch); // Then assertThat(matchedCount).isEqualTo(2); From 6388f3d4d90ff5e163ba60d2ea9e9c9100aa060f Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 14:35:47 +0900 Subject: [PATCH 11/21] Rename test case to be more specific --- src/test/java/com/company/text/SearchableStringTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/company/text/SearchableStringTest.java b/src/test/java/com/company/text/SearchableStringTest.java index cc422c5..95a4a3d 100644 --- a/src/test/java/com/company/text/SearchableStringTest.java +++ b/src/test/java/com/company/text/SearchableStringTest.java @@ -51,7 +51,7 @@ public void buildIncrementMap_when_ABcAB_IsGiven() { } @Test - public void searchText_when_ABcAB_IsGiven() { + public void searchText_whenSearchableTextContainsTheGivenStringIn2SubString_thenReturning2() { // Given String textToSearch = "abcabd"; SearchableString searchableString = new SearchableString("XXXX" + textToSearch + "XXXX" + textToSearch); From 8e204f4c3e80ca8a8e4ee02574c352f86d772dfe Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 14:45:00 +0900 Subject: [PATCH 12/21] Add document and comment --- .../com/company/text/SearchableString.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index c0741a8..8017bc3 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -39,6 +39,14 @@ public int searchText(String textToSearch) { return count; } + /** + * Referencing KMP algorithm + * Build a start-index-increment map when searching text + * Key: length of first matching chars, Value: How many a start index increments. + * + * @param text to build + * @return a start-index-increment map + */ Map buildIncrementMap(String text) { HashMap map = new HashMap<>(); for (int partialLength = 2; partialLength < text.length(); partialLength++) { @@ -53,18 +61,22 @@ Map buildIncrementMap(String text) { return map; } - private int getMaxLengthMatchingPrefixAndPostfix(String subStr) { - System.out.println("subString: " + subStr); - int maxLength = 0; - for (int prefixLength = 1; prefixLength < subStr.length(); prefixLength++) { - String pre = subStr.substring(0, prefixLength); - String post = subStr.substring(subStr.length() - prefixLength); + /** + * @param string to check the max length of matching postfix and prefix + * @return max length of matching postfix and prefix + */ + private int getMaxLengthMatchingPrefixAndPostfix(String string) { + System.out.println("subString: " + string); + int maxLengthMatchingPrefixAndPostfix = 0; + for (int prefixLength = 1; prefixLength < string.length(); prefixLength++) { + String pre = string.substring(0, prefixLength); + String post = string.substring(string.length() - prefixLength); System.out.println("pre: " + pre + " post: " + post + " prefixLen: " + prefixLength); if (pre.equals(post)) { System.out.println("matched"); - maxLength = prefixLength; + maxLengthMatchingPrefixAndPostfix = prefixLength; } } - return maxLength; + return maxLengthMatchingPrefixAndPostfix; } } From 698036dbdf6388039dbc504594723f2f7450c90c Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 15:08:04 +0900 Subject: [PATCH 13/21] Rewrite the logs --- .../java/com/company/text/SearchableString.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index 8017bc3..15be61a 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -13,7 +13,7 @@ public SearchableString(String text) { public int searchText(String textToSearch) { integerIntegerMap = this.buildIncrementMap(textToSearch); - System.out.println("start to search"); + System.out.println("\nStart to search " + textToSearch + " in " + this.text); int count = 0; for (int startIndex = 0; startIndex < text.length() - textToSearch.length() + 1; ) { int matchedCharCount = 0; @@ -29,6 +29,7 @@ public int searchText(String textToSearch) { } if (matchedCharCount == textToSearch.length()) { count++; + System.out.println("matched in " + startIndex); startIndex++; } else if (matchedCharCount == 0 || matchedCharCount == 1) { startIndex++; @@ -48,6 +49,7 @@ public int searchText(String textToSearch) { * @return a start-index-increment map */ Map buildIncrementMap(String text) { + System.out.println("\nIncrementMap has started for " + text); HashMap map = new HashMap<>(); for (int partialLength = 2; partialLength < text.length(); partialLength++) { String partialString = text.substring(0, partialLength); @@ -55,9 +57,12 @@ Map buildIncrementMap(String text) { if (maxLengthToMatch == 0) { map.put(partialLength, 1); } else { - map.put(partialLength, partialLength - maxLengthToMatch); + int increment = partialLength - maxLengthToMatch; + map.put(partialLength, increment); + System.out.println("Key: " + partialString.length() + " IncrementValue: " + increment); } } + System.out.println("IncrementMap has been built."); return map; } @@ -66,14 +71,12 @@ Map buildIncrementMap(String text) { * @return max length of matching postfix and prefix */ private int getMaxLengthMatchingPrefixAndPostfix(String string) { - System.out.println("subString: " + string); int maxLengthMatchingPrefixAndPostfix = 0; for (int prefixLength = 1; prefixLength < string.length(); prefixLength++) { String pre = string.substring(0, prefixLength); String post = string.substring(string.length() - prefixLength); - System.out.println("pre: " + pre + " post: " + post + " prefixLen: " + prefixLength); if (pre.equals(post)) { - System.out.println("matched"); + System.out.println("prefix: " + pre + " post: " + post + " matched in " + string); maxLengthMatchingPrefixAndPostfix = prefixLength; } } From 9c549f0acf298c2a6251de8fc9df200e8389d51e Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 15:08:21 +0900 Subject: [PATCH 14/21] Add test case for searchText --- .../com/company/text/SearchableStringTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/company/text/SearchableStringTest.java b/src/test/java/com/company/text/SearchableStringTest.java index 95a4a3d..de74272 100644 --- a/src/test/java/com/company/text/SearchableStringTest.java +++ b/src/test/java/com/company/text/SearchableStringTest.java @@ -51,7 +51,7 @@ public void buildIncrementMap_when_ABcAB_IsGiven() { } @Test - public void searchText_whenSearchableTextContainsTheGivenStringIn2SubString_thenReturning2() { + public void searchText_whenSearchableTextContainsTheGivenStringIn2SubString_thenReturning2_case1() { // Given String textToSearch = "abcabd"; SearchableString searchableString = new SearchableString("XXXX" + textToSearch + "XXXX" + textToSearch); @@ -62,4 +62,17 @@ public void searchText_whenSearchableTextContainsTheGivenStringIn2SubString_then // Then assertThat(matchedCount).isEqualTo(2); } + + @Test + public void searchText_whenSearchableTextContainsTheGivenStringIn2SubString_thenReturning2_case2() { + // Given + String textToSearch = "abcabd"; + SearchableString searchableString = new SearchableString("XXXXabc" + textToSearch + "XXXX" + textToSearch); + + // When + int matchedCount = searchableString.searchText(textToSearch); + + // Then + assertThat(matchedCount).isEqualTo(2); + } } \ No newline at end of file From 28fb15d0aa91183f3aab26773208b4daa1fe660a Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 16:04:17 +0900 Subject: [PATCH 15/21] Fix buildIncrementMap to find matching postfix and prefix in full string --- src/main/java/com/company/text/SearchableString.java | 2 +- src/test/java/com/company/text/SearchableStringTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index 15be61a..bf84509 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -51,7 +51,7 @@ public int searchText(String textToSearch) { Map buildIncrementMap(String text) { System.out.println("\nIncrementMap has started for " + text); HashMap map = new HashMap<>(); - for (int partialLength = 2; partialLength < text.length(); partialLength++) { + for (int partialLength = 2; partialLength <= text.length(); partialLength++) { String partialString = text.substring(0, partialLength); int maxLengthToMatch = getMaxLengthMatchingPrefixAndPostfix(partialString); if (maxLengthToMatch == 0) { diff --git a/src/test/java/com/company/text/SearchableStringTest.java b/src/test/java/com/company/text/SearchableStringTest.java index de74272..dd92745 100644 --- a/src/test/java/com/company/text/SearchableStringTest.java +++ b/src/test/java/com/company/text/SearchableStringTest.java @@ -36,7 +36,7 @@ public void buildIncrementMap_whenAAIsGiven_thenIncrementHasNoElement() { @Test public void buildIncrementMap_when_ABcAB_IsGiven() { // Given - String textToSearch = "abcabd"; + String textToSearch = "abcab"; SearchableString searchableString = new SearchableString(""); // When From a6fbdca6f3aecce5191934e58713d37c6a6f517d Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 16:06:06 +0900 Subject: [PATCH 16/21] Fix text buildIncrementMap when given string length is 2 --- src/test/java/com/company/text/SearchableStringTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/company/text/SearchableStringTest.java b/src/test/java/com/company/text/SearchableStringTest.java index dd92745..5174678 100644 --- a/src/test/java/com/company/text/SearchableStringTest.java +++ b/src/test/java/com/company/text/SearchableStringTest.java @@ -24,13 +24,14 @@ public void searchText_whenSearchingAVAInAVAVA_thenReturning2() { public void buildIncrementMap_whenAAIsGiven_thenIncrementHasNoElement() { // Given String textToSearch = "aa"; - SearchableString avava = new SearchableString("avava"); + SearchableString avava = new SearchableString(""); // When Map aaIncrementMap = avava.buildIncrementMap(textToSearch); // Then - assertThat(aaIncrementMap).hasSize(0); + assertThat(aaIncrementMap).hasSize(1); + assertThat(aaIncrementMap.get(2)).isEqualTo(1); } @Test From b7af98b8856d94f5d516f0bb68cddf2866ba3112 Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 17:01:43 +0900 Subject: [PATCH 17/21] Modify buildIncrementMap --- .../com/company/text/SearchableString.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index bf84509..131046c 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -49,21 +49,30 @@ public int searchText(String textToSearch) { * @return a start-index-increment map */ Map buildIncrementMap(String text) { - System.out.println("\nIncrementMap has started for " + text); - HashMap map = new HashMap<>(); - for (int partialLength = 2; partialLength <= text.length(); partialLength++) { - String partialString = text.substring(0, partialLength); - int maxLengthToMatch = getMaxLengthMatchingPrefixAndPostfix(partialString); - if (maxLengthToMatch == 0) { - map.put(partialLength, 1); + HashMap incrementMap = new HashMap<>(); + for (int startIndex = 1; startIndex < text.length(); startIndex++) { + int matchedLength = startIndex + 1; + for (int i = 0; i < text.length() - startIndex; i++) { + char ch1 = text.charAt(i); + char leftCutText = text.charAt(i + startIndex); + + if (ch1 == leftCutText) { + incrementMap.put(matchedLength, startIndex); + System.out.println("matched: " + matchedLength + " char:" + ch1 + " increment: " + startIndex); + matchedLength++; + } else { + break; + } + } + + if (matchedLength == startIndex + 1) { + incrementMap.put(matchedLength, 1); + System.out.println("matched: " + matchedLength + " increment: 1"); } else { - int increment = partialLength - maxLengthToMatch; - map.put(partialLength, increment); - System.out.println("Key: " + partialString.length() + " IncrementValue: " + increment); + startIndex = matchedLength; } } - System.out.println("IncrementMap has been built."); - return map; + return incrementMap; } /** From 7a8bdc25ba87dcfc46dfc79575c06c6eb62d2446 Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 17:56:46 +0900 Subject: [PATCH 18/21] Fix buildIncrementMap to traverse to the end of array --- .../com/company/text/SearchableString.java | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index 131046c..326af9a 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -29,8 +29,8 @@ public int searchText(String textToSearch) { } if (matchedCharCount == textToSearch.length()) { count++; - System.out.println("matched in " + startIndex); - startIndex++; + System.out.println("all matched in " + startIndex); + startIndex = startIndex + this.integerIntegerMap.get(matchedCharCount); } else if (matchedCharCount == 0 || matchedCharCount == 1) { startIndex++; } else { @@ -49,8 +49,9 @@ public int searchText(String textToSearch) { * @return a start-index-increment map */ Map buildIncrementMap(String text) { + System.out.println("IncrementMap build started for " + text); HashMap incrementMap = new HashMap<>(); - for (int startIndex = 1; startIndex < text.length(); startIndex++) { + for (int startIndex = 1; startIndex < text.length(); ) { int matchedLength = startIndex + 1; for (int i = 0; i < text.length() - startIndex; i++) { char ch1 = text.charAt(i); @@ -58,37 +59,22 @@ Map buildIncrementMap(String text) { if (ch1 == leftCutText) { incrementMap.put(matchedLength, startIndex); - System.out.println("matched: " + matchedLength + " char:" + ch1 + " increment: " + startIndex); + System.out.println("matchedLength: " + matchedLength + " increment: " + startIndex); matchedLength++; } else { + incrementMap.put(matchedLength, 1); + System.out.println("matchedLength: " + matchedLength + " increment: " + 1); break; } } if (matchedLength == startIndex + 1) { - incrementMap.put(matchedLength, 1); - System.out.println("matched: " + matchedLength + " increment: 1"); + startIndex++; } else { - startIndex = matchedLength; + startIndex = matchedLength + 1; } } + System.out.println("IncrementMap has been built."); return incrementMap; } - - /** - * @param string to check the max length of matching postfix and prefix - * @return max length of matching postfix and prefix - */ - private int getMaxLengthMatchingPrefixAndPostfix(String string) { - int maxLengthMatchingPrefixAndPostfix = 0; - for (int prefixLength = 1; prefixLength < string.length(); prefixLength++) { - String pre = string.substring(0, prefixLength); - String post = string.substring(string.length() - prefixLength); - if (pre.equals(post)) { - System.out.println("prefix: " + pre + " post: " + post + " matched in " + string); - maxLengthMatchingPrefixAndPostfix = prefixLength; - } - } - return maxLengthMatchingPrefixAndPostfix; - } } From 4e0265ba4ccfae7f3ab8374e1bf0d61ba1393dea Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 18:51:45 +0900 Subject: [PATCH 19/21] Simplify increasing startIndex of traversing in buildIncrementMap --- src/main/java/com/company/text/SearchableString.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index 326af9a..6ab45fd 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -67,12 +67,7 @@ Map buildIncrementMap(String text) { break; } } - - if (matchedLength == startIndex + 1) { - startIndex++; - } else { - startIndex = matchedLength + 1; - } + startIndex = matchedLength; } System.out.println("IncrementMap has been built."); return incrementMap; From 4ac60f53c4b09e2caf8a91133070af1e92691b95 Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 19:38:25 +0900 Subject: [PATCH 20/21] Modify the way of referencing the last index traversed --- .../java/com/company/text/SearchableString.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index 6ab45fd..42b91fa 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -52,22 +52,22 @@ Map buildIncrementMap(String text) { System.out.println("IncrementMap build started for " + text); HashMap incrementMap = new HashMap<>(); for (int startIndex = 1; startIndex < text.length(); ) { - int matchedLength = startIndex + 1; + int currentIndex = startIndex; for (int i = 0; i < text.length() - startIndex; i++) { char ch1 = text.charAt(i); char leftCutText = text.charAt(i + startIndex); - + int partialMatchingLength = currentIndex + 1; if (ch1 == leftCutText) { - incrementMap.put(matchedLength, startIndex); - System.out.println("matchedLength: " + matchedLength + " increment: " + startIndex); - matchedLength++; + incrementMap.put(partialMatchingLength, startIndex); + System.out.println("matchedLength: " + partialMatchingLength + " increment: " + startIndex); + currentIndex++; } else { - incrementMap.put(matchedLength, 1); - System.out.println("matchedLength: " + matchedLength + " increment: " + 1); + incrementMap.put(currentIndex + 1, 1); + System.out.println("matchedLength: " + partialMatchingLength + " increment: " + 1); break; } } - startIndex = matchedLength; + startIndex = currentIndex + 1; } System.out.println("IncrementMap has been built."); return incrementMap; From 900779bd852e9321aaea44d2cb9a41f9377f95e8 Mon Sep 17 00:00:00 2001 From: rikim Date: Sun, 17 May 2020 19:48:53 +0900 Subject: [PATCH 21/21] Traverse chars from startIndex instead of zero index --- src/main/java/com/company/text/SearchableString.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/company/text/SearchableString.java b/src/main/java/com/company/text/SearchableString.java index 42b91fa..21bf12f 100644 --- a/src/main/java/com/company/text/SearchableString.java +++ b/src/main/java/com/company/text/SearchableString.java @@ -53,14 +53,13 @@ Map buildIncrementMap(String text) { HashMap incrementMap = new HashMap<>(); for (int startIndex = 1; startIndex < text.length(); ) { int currentIndex = startIndex; - for (int i = 0; i < text.length() - startIndex; i++) { - char ch1 = text.charAt(i); - char leftCutText = text.charAt(i + startIndex); + for (; currentIndex < text.length(); currentIndex++) { + char ch1 = text.charAt(currentIndex - startIndex); + char leftCutText = text.charAt(currentIndex); int partialMatchingLength = currentIndex + 1; if (ch1 == leftCutText) { incrementMap.put(partialMatchingLength, startIndex); System.out.println("matchedLength: " + partialMatchingLength + " increment: " + startIndex); - currentIndex++; } else { incrementMap.put(currentIndex + 1, 1); System.out.println("matchedLength: " + partialMatchingLength + " increment: " + 1);