我必须制作一个算法,找出给定字符串中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));
}
}
}
答案 0 :(得分:1)
使用String方法:matches(String regex)可能是解决此问题的最简单方法。
您可以通过多种方式使用它,例如:创建一个循环,检查单个出现的“SUN”并存储++值(如果找到),然后用String替换一个实例replaceFirst(String regex,String replacement)从正在检查的字符串中删除一个实例的方法。
有关正则表达式的用法,请查看以下链接:
Tutorial(某些表达方式可能因语言而异,请查看上述链接以确认)。
答案 1 :(得分:0)
由于你有3个嵌套循环,最里面的循环一遍又一遍地重复(几乎)相同的搜索。
首先解析字符串,删除所有非必要字母并折叠重复字母:
SSRUUWSUNXXS --> S(2) U(2) S U N S
E.g。解析结果为LetterCount[]
,其中类有2个字段char letter
和int 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;
}