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

时间:2015-06-21 02:18:46

标签: java string algorithm substring

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

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

我只查找子字符串中第一个和最后一个字符相同的所有子字符串的计数。正如您所看到的,我只在下面的代码中从函数返回count。我想在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秒。

3 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:3)

这是快速的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<Character, Long> map。但它很慢。

答案 2 :(得分:0)

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

算法步骤

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

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

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

    在此算法中,重复字符串将计数。