在数组中查找模式

时间:2013-03-06 15:44:18

标签: java algorithm

我想知道是否有更简单的方法在数组中找到模式?

说我正在寻找给定数组中的一个模式: A)微笑,皱眉,微笑,皱眉等 B)微笑,愤怒,皱眉,微笑,愤怒,皱眉等 C)微笑,微笑,微笑

现在说给出的数组与模式A匹配:

愤怒,愤怒,愤怒,Smile, Frown, Smile, Frown, Smile, Frown,愤怒,皱眉,愤怒,皱眉,微笑

突出显示的部分是与模式A匹配的部分以及我想要存储在列表中的部分。

现在我有这样的事情:

For each element in the array
check to see if element is smile
if element is smile, check to see if next element is frown
if element is smile and next element is frown - store away in a list 
set a boolean saying we've found pattern A

if the boolean value is false and we did not find the smile frown pattern
For each element in the array
check to see if element is smile
if element is smile, check to see if next element is angry,
is next element is angry, check to see if next next element is frown
if element is smile, next element is angry, next next element is frown - store away in a list
set a boolean saying we've found pattern B

if boolean value is false for both finding pattern A and pattern B search for pattern C

有更好的方法吗?我觉得这总体上很糟糕......

5 个答案:

答案 0 :(得分:3)

您可以将数组转换为字符串,并将其与任何正则表达式模式匹配。

UPD:可以是prefix tree可以帮助您。首先将所有模式添加到trie中,然后再次匹配您的数组。但那将非常像一个本土的正则表达式引擎。

答案 1 :(得分:2)

更新:我实施了我描述的方法。

运行以下代码返回:

First match against pattern found at index 3
No match found.

为了简单起见,我将代码和测试代码放在一个类中。执行此工作的函数是findPatternIndex。其余的是简单的测试,初始化和显示逻辑。

import java.util.LinkedHashMap;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

public class PatternMatching {

  private final Map<String, Character> encodedWords = new LinkedHashMap<String, Character>();

  @Before
  public void init() {
    encodedWords.put("Angry", 'A');
    encodedWords.put("Smile", 'S');
    encodedWords.put("Frown", 'F');
  }

  public int findPatternIndex(final String[] array, final String pattern) {
    final StringBuffer encodedSequence = new StringBuffer();
    for (final String element : array) {
      encodedSequence.append(encodedWords.get(element));
    }
    return encodedSequence.toString().indexOf(pattern);
  }

  private void displayFindings(final int index) {
    if (index==-1) {
      System.out.println("No match found.");
    } else {
      System.out.println("First match against pattern found at index " + index);
    }
  }

  @Test
  public void shouldFindOneMatchThenNone() {
    final String[] array = {"Angry","Angry","Angry","Smile","Frown","Smile","Frown","Smile","Frown","Angry","Frown","Angry","Frown","Smile"};
    String pattern="SFSF";
    displayFindings(findPatternIndex(array, pattern));
    pattern="AAF";
    displayFindings(findPatternIndex(array, pattern));
  }

}

如果预先不知道填充数组的单词,则可以进一步更新代码以动态构建编码的词。显示所有匹配的索引而不仅仅是第一个匹配也很简单。

答案 2 :(得分:2)

KMP string search algorithm的修改版本在这里很有用。

以下是一些示例Java代码:http://www.fmi.uni-sofia.bg/fmi/logic/vboutchkova/sources/KMPMatch.java

需要考虑的一些差异:

  • 应该构建它以同时处理多个搜索词。在您的情况下,有多种模式,例如:Smile, Frown,Smile, Angry, Frown,
  • 重复的模式本身只是同一个单词的多次重复。在发现单个单词的位置后,您可以在搜索完成后组合找到的彼此相邻的模式。这将允许您获得重复的完整完整模式,例如:Smile, Frown, Smile, Frown, Smile, Frown,

希望这有帮助。

答案 3 :(得分:0)

使用Arrays.toString(Object[] a)将数组转换为String,然后查找您的模式。

例如Arrays.toString(new String[] { "a", "b" })返回"[a, b]"

答案 4 :(得分:0)

可能有更简单的解决方案,但您可以在字符串的帮助下完成。优点是,您可以使用已经过测试和执行的代码。缺点是,您必须将数组转换为String

创建String您需要从值空间到字符串空间的映射。所以例如

{0, 1, 2} -> {"0", "1", "2"}
{0, 1, ..., 99, 100} -> {"_0", "_1", ..., "_99", "_100"}
{SMILE, FROWN, ANGRY} -> {"S", "F", "A"}
{"Smile", "Frown", "Angry"} -> {"Smile", "Frown", "Angry"}

您需要注意映射的值不能相互交互。例如,映射

{0, 1, ..., 10} -> {"0", "1", ..., "10"}

将是无效的映射,因为如果"10"1后跟0,或者它是10,则无法找到。

示例:假设您的数组包含{ANGRY. SMILE, FROWN, SMILE, FROWN, SMILE, FROWN, SMILE}。然后,您映射的String将为"ASFSFSFS"

定义模式接下来,您需要定义模式。这只是一个String,其中包含正确的模式,就像您希望在映射的String中找到它一样。

示例:在您的情况下,那将是

String pattern = "SFSFSF";

将字符串与模式匹配:现在,您可以使用indexOf()来查找模式。

int start = mappedString.indexOf(pattern);

这将为您提供patternmappedString的第一个外观索引。如果它返回-1,则在字符串中找不到您的模式。

存储模式:否则,您可以将模式存储在列表中。

if (start > 0) storePatternInList(yourList, new ObjectEnum[]{SMILE, FROWN, SMILE, FROWN, SMILE, FROWN});

您可以使用mappedString.subString(start+pattern.length()).indexOf(pattern)再次搜索。找到下一个样子。