关于java:是否有一个技巧/算法,通过它我们可以在O(n)时间内找到所有可能的子串

Is there a trick/algorithm by which we can find all substrings possible in O(n) time

我有一个蛮力的解决方案来计算O(n^2)时间内输入字符串中的所有子字符串。当我的输入字符串很长时需要很长时间。

我们怎样才能在O(N)时间内找到所有可能的子串呢?

我只查找子字符串中第一个和最后一个字符相同的所有子字符串的计数。如您所见,我只返回下面代码中函数的count。我想在O(N)时间内完成

我的强力解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// I am calculating count of all substrings where first and last substring character are equal

public class Solution {

public static void main(String[] args) {

    String inputString ="ababaca";

    System.out.println(findSubstringByBruteForcce(inputString, inputString.length()));

}

private static long findSubstringByBruteForcce(String inputString, int length) {
    long count = 0;    
    for (int i = 0; i < length; i++) {
        for (int j = 1; j <= length - i; j++) {
            String str = inputString.substring(i, i + j);
            if(str.length() == 1){
                count = count + 1;
            }else {
                if(str.substring(0, 1).equals(str.substring(str.length() - 1, str.length()))){
                    count = count + 1;
                }
            }
        }
    }
    return count;
}

}

如何优化上述解决方案并在O(N)时间内找到答案?输入字符串可以非常大(约10^6长),强力在大约20秒内运行。我希望最大运行时间在2秒以下。


由于子串标识是由边界索引而不是内容决定的,所以只需计算每个字母的频率,然后对每个字母求和(频率+1)*频率DIV 2,因为每对重复但不考虑顺序的字母位置都会产生一个计数的子串。


这很快,但内存太多:

1
2
3
4
5
6
7
public static long findSubstringByCharacterMap(String s, int length) {
    long count = 0;
    long[] map = new long[Character.MAX_VALUE + 1];
    for (int i = 0; i < length; ++i)
        count += ++map[s.charAt(i)];
    return count;
}

如果字符串只包含单字节字符,那么long[] map的大小可以是256。

你可以用Map map重写long[] map。但速度很慢。


我有一个解决方案,它使用大小为256(最大ASCII值为255)的数组的恒定额外空间以及时间复杂性。

算法步骤

  • 创建一个256的数组。
  • 在ans中添加当前元素的当前频率,并更新字符串中当前元素的频率。
  • 遍历整个字符串。
  • 在ans中添加字符串长度。

    这里是我的Java实现代码,告诉我如果我错了或者我有错失理解的问题。

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import java.util.*;
    import java.lang.*;
    import java.io.*;


    class Solution
    {
        public static void main (String[] args) throws java.lang.Exception
        {
            String str="aabbab#cd#e";
            int[] array=new int[256];
            int ans=0;
            for(int i=0;i<str.length();i++){
                ans+=array[(int)str.charAt(i)];
                array[(int)str.charAt(i)]++;
            }
            ans=ans+str.length();
            System.out.print(ans);
           
        }
    }

    在这个算法中,重复的字符串将计数。