如何在字符串中找到一系列字符(忽略其间的字符)(JAVA)

时间:2015-10-10 15:49:38

标签: java string

我必须制作一个算法,找出给定字符串中SUN序列的重复次数。

序列必须按顺序包含字符S-U-N,即使它们之间有其他字符,也要计入其SUN度。每次出现SUN都会使度数增加1.例如,序列GUSN,GSUN和SSRUUWN的SUN度分别为0,1和4。

必须遵循以下事项:

1>首先收到T整数个案例。 1≤T≤1000//假设

2 - ;程序每次接收一个字符串并计算序列的程度(重复)。 1≤| string |≤1000//假设

示例输入:

3

GUSN

GSUN

SSRUUWN

示例输出:

0

1

4

我已经完成了该计划,问题在于它太慢了。

到目前为止,这是我的计划:

已更新

公共类解决方案{

private static Scanner STDIN = new Scanner(System.in);

private static int t = 0;


/**
 * Sets value of t.
 */
public static void setT(int k){
    t=k+1;
}

/**
 * Gets repetitions (degree) of the sequence CAT inside a given
 * sequence, no matter if there are another characters in 
 * between.
 * @return degree repetitions of the sequence
 */
public static long getDegree(String sequence){
    long degree = 0;

    char[] sequenceChars = new char[t];
    sequenceChars = sequence.toCharArray();

    for(int i=0; i<sequenceChars.length; i++){
        if(sequenceChars[i]=='S'){
            for(int n=i+1; n<sequenceChars.length; n++){
                if(sequenceChars[n]=='U'){
                    for(int k=n+1; k<sequenceChars.length; k++){
                        if(sequenceChars[k]=='N'){
                        degree++;
                        }
                    }
                }
            }
        }
    }
    return degree;

}

public static void main(String[] args) {
    // TODO Auto-generated method stub

    int t = STDIN.nextInt();
    setT(t);

    for(int i = 0; i<t; i++){
        String sequence = STDIN.next();
        System.out.println(getDegree(sequence));
    }

}

}

以前的版本

公共类解决方案{

private static Scanner STDIN = new Scanner(System.in);

/**
 * Gets repetitions (degree) of the sequence SUN inside a given
 * sequence, no matter if there are another characters in 
 * between.
 * @return degree repetitions of the sequence
 */
public static long getDegree(String sequence){
    long degree = 0;

    for(int i=0; i<sequence.length(); i++){
        if(sequence.charAt(i)=='S'){
            for(int n=i+1; n<sequence.length(); n++){
                if(sequence.charAt(n)=='U'){
                    for(int k=n+1; k<sequence.length(); k++){
                        if(sequence.charAt(k)=='N'){
                        degree++;
                        }
                    }
                }
            }
        }
    }
    return degree;

}

public static void main(String[] args) {
    // TODO Auto-generated method stub

    int t = STDIN.nextInt();

    for(int i = 0; i<t; i++){
        String sequence = STDIN.next();
        System.out.println(getDegree(sequence));
    }
}

}

3 个答案:

答案 0 :(得分:1)

使用String方法:matches(String regex)可能是解决此问题的最简单方法。

您可以通过多种方式使用它,例如:创建一个循环,检查单个出现的“SUN”并存储++值(如果找到),然后用String替换一个实例replaceFirst(String regex,String replacement)从正在检查的字符串中删除一个实例的方法。

有关正则表达式的用法,请查看以下链接:

Oracle documentation

Tutorial(某些表达方式可能因语言而异,请查看上述链接以确认)。

答案 1 :(得分:0)

由于你有3个嵌套循环,最里面的循环一遍又一遍地重复(几乎)相同的搜索。

首先解析字符串,删除所有非必要字母并折叠重复字母:

SSRUUWSUNXXS  -->  S(2)  U(2)  S  U  N  S

E.g。解析结果为LetterCount[],其中类有2个字段char letterint count

然后在这个优化序列上进行三重循环,乘以计数:

  S(2) * U(2) * N(1)
+ S(2) * U(1) * N(1)
+ S(1) * U(1) * N(1)
= 4 + 2 + 1
= 7

答案 2 :(得分:0)

我找到了一种非常快速的方法。 数组Sa在索引i处存储序列SUN包含在从i开始的输入字符串的子字符串中的频率。 Ua存储序列UN包含的频率。并且Na存储N的包含频率。 这是一种记忆形式 https://en.wikipedia.org/wiki/Memoization

public static long getDegree(String sequence){
  if(sequence.length() == 0) return 0;
  long degree = 0;
  char[] array = sequence.toCharArray();

  long[] Sa = new long[array.length];
  long[] Ua = new long[array.length];
  long[] Na = new long[array.length];

  if(array[array.length - 1] == 'N') Na[array.length - 1] = 1;
  else Na[array.length - 1] = 0;
  Ua[array.length - 1] = 0;
  Sa[array.length - 1] = 0;

  for(int i = array.length - 2; i >= 0; i--) {
    char c = array[i];
    Na[i] = Na[i + 1] + (c == 'N' ? 1 : 0);
    Ua[i] = Ua[i + 1] + (c == 'U' ? Na[i + 1] : 0);
    Sa[i] = Sa[i + 1] + (c == 'S' ? Ua[i + 1] : 0);
  }
  return Sa[0];
}

修改 我注意到你甚至不需要阵列。你可以用简单的长号替换它们,使它更快。

public static long getDegree(String sequence){
  if(sequence.length() == 0) return 0;
  long degree = 0;
  char[] array = sequence.toCharArray();

  long S = 0;
  long U = 0;
  long N = 0;

  for(int i = array.length - 1; i >= 0; i--) {
    char c = array[i];
    S = S + (c == 'S' ? U : 0);
    U = U + (c == 'U' ? N : 0);
    N = N + (c == 'N' ? 1 : 0);
  }
  return S;
}