【问题标题】:Is there a trick/algorithm by which we can find all substrings possible in O(n) time是否有一种技巧/算法可以让我们在 O(n) 时间内找到所有可能的子字符串
【发布时间】:2015-06-21 02:18:45
【问题描述】:

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

我们如何在 O(n) 时间内找到所有可能的子字符串?

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

我的蛮力解决方案:

// 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 秒。

【问题讨论】:

  • 您是在寻找实际的子串还是子串计数?您是在查找所有子字符串(包括重复项)还是仅查找唯一子字符串?
  • 我只查找子字符串中第一个和最后一个字符相同的所有子字符串的计数。如您所见,我只从函数返回计数。
  • 我投票结束这个问题,因为这是一个正在进行的编程竞赛。

标签: java string algorithm substring


【解决方案1】:

由于子字符串标识由边界索引而不是内容确定,因此计算每个字母的频率就足够了,然后对每个字母求和(频率 + 1)* 频率 div 2,因为每对具有重复但不考虑顺序的字母位置会产生一个计数的子字符串。

【讨论】:

  • 真正的天才解决方案!!非常感谢:)
  • 如果只需要子字符串计数(包括重复项),此方法可能是最快的。假设字母大小≪字符串长度,它应该是 O(N)。
  • 对此进行说明。这有希望,但有很多绒毛。一些数学会很好。
  • 为什么是(freq + 1)*freq / 2?我认为每个字母的正确公式是C(2, freq),其中C(k, n)binomial coefficient
  • @FalconUA 单字母子串计数。
【解决方案2】:

这是 O(n) 快但内存太多:

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。

您可以将long[] map 重写为Map&lt;Character, Long&gt; map。但是速度很慢。

【讨论】:

    【解决方案3】:

    我有一个解决方案,它占用大小为 256(最大 Ascii 值为 255)和 o(n) 时间复杂度的数组的恒定额外空间。

    算法步骤

    1. 创建一个 256 的数组。
    2. 在 ans 中添加当前元素的当前频率并更新 string 中当前元素的频率。
    3. 遍历整个字符串。
    4. 在ans中添加字符串长度。

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

    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);
    		
    	}
    }

    在这个算法中,重复的字符串会被计算在内。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-12
      • 2019-05-20
      相关资源
      最近更新 更多