找出无序的anagramic对子串的数量

时间:2015-03-22 06:11:27

标签: java string java.util.scanner anagram

我正在尝试解决以下问题: https://www.hackerrank.com/challenges/sherlock-and-anagrams

这是我的代码

import java.util.*;
public class Solution {

public static boolean check(String s1,String s2)
{

    int [] count1 = new int[26];
    for( int i = 0; i < s1.length(); i++ )
    {
        char ch1 = s1.charAt(i);
        count1[ch1-'a']++;
    }

    int [] count2 = new int[26];
    for( int i = 0; i < s2.length(); i++ )
    {
        char ch2 = s2.charAt(i);
        count2[ch2-'a']++;
    }

    int count =0;
    for(int j=0;j<26;j++)
    {
        count = count + Math.abs(count1[j]-count2[j]);
    }

    if(count ==0)
            return true;
    else return false;
}
public static void main(String[] args) {

    String s,sub;
    int i,c,len;
    List<String> all = new ArrayList<>();

    Scanner in = new Scanner(System.in);
    int t = Integer.parseInt(in.nextLine());

      while((t--)>0)
    {
          s  = in.nextLine();
          len = s.length();   
       for( c = 0 ; c < len ; c++ )
       {
           for( i = 1 ; i <= len - c ; i++ )
          {
             sub = s.substring(c, c+i);
            all.add(sub);
          }
       }

      String[] arr = new String[all.size()];
      for( i = 0; i < all.size(); i++) 
              arr[i] = all.get(i);

          int l=0;
          for (int m=0;m<arr.length;m++)
          {
              for(int n=m+1;n<arr.length;n++)
               {
                  if(check(arr[m],arr[n]))
                         l++;
              }
          }

          System.out.println(l);all.clear();
    }

}
}

我的代码适用于少数具有小字符串的测试用例但如果字符串大小太大则无法工作

示例输入

5
ifailugtyovhdfuhdouarjsnrbfpvmupwjjjfiwneogwnoegnoegneognoewhrlkpekxxnebfrwibylcvkfealgonjkzw
gffryqktmwocejbrexfidpjfgrrkpowoxwggxaknmltjcpazgtnakcfbveieivoenwvpnoevvneocogzatyskqjyorcftw
uqlzvuzgkwhkkrrfpwarkckansgabfclzgnumdrojexnofeqjnqnxwidhbvbenevun9evnnv9euxxhfwargwkikjq
sygjxynvofnvirarcoacwnhxyqlrviikfuiuotifznqmzpjrxycnqkeibvibvewioebvitkryutpqvbgbgthfges
mkenscyiamnwlpxytkndjsygifmqlqibxxqlauxamfviftquntvkwppxrzuncyenavebiobeviobeiobeibvcfivtigv

我的输出

4s : Terminated due to timeout

有没有更好的方法来解决它或更改现有代码,以便执行时间在4分钟内

2 个答案:

答案 0 :(得分:1)

除了提前终止。您可以使用HashMap,键是长度,值是相同长度的子串列表。存储子字符串并仅检查&#39;值&#39;中的元素。 虽然如果长度不同,你可能会认为它与早期终止的工作方式相同,但它会产生影响并且不会提前终止问题。

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int x=sc.nextInt();
        for(int k=0; k<x; k++){
            String str1=sc.next();
            HashMap<Integer,ArrayList<String>> sub= getSub(str1);
            int counter=0;
            for(int t=1; t<=str1.length(); t++){
                ArrayList<String> subsl= sub.get(t);
                for(int i=0; i<subsl.size()-1; i++){
                    for(int j=i+1; j<subsl.size(); j++){
                        if(isAnagram(subsl.get(j),subsl.get(i))){
                            counter++;
                        }
                    }   
                }
            }
            System.out.println(counter);
        }
    }
    public static HashMap<Integer,ArrayList<String>> getSub(String str1){
        HashMap<Integer,ArrayList<String>> ret= new HashMap<Integer,ArrayList<String>>();
        for(int i=0; i<str1.length(); i++){
            for(int j=i; j<str1.length(); j++){
                if(!ret.containsKey(str1.substring(i, j+1).length())){  
                    ArrayList<String> x= new ArrayList<String>();
                    x.add(str1.substring(i, j+1));
                    ret.put(str1.substring(i, j+1).length(), x);
                }
                else
                    ret.get(str1.substring(i, j+1).length()).add(str1.substring(i, j+1));
            }
        }
        return ret;
    }

    public static boolean isAnagram(String a1, String a2){
        int count1[]= new int[26];
        int count2[]= new int[26];
        if(a1.length()!=a2.length())
            return false;
        for(int i=0; i<a1.length(); i++){
            count1[(int)a1.charAt(i)-97]++;
            count2[(int)a2.charAt(i)-97]++;
        }
        for(int i=0; i<26; i++){
            if(count1[i]!=count2[i])
                return false;
        }
        return true;
    }
} 

如果你想让它更快,那么改变HashMap以包含一个具有所有26个字母的计数的对象。那显然需要更多的记忆,所以你可以得到一些中间长度的东西,并说出字母a,b,c(或3个这样的字母)的数量。 为了使检查有效,使用位操作来编码所有这些(长度,a的计数,b的计数和c的计数)。虽然注意不要超过Integer的位数。

答案 1 :(得分:0)

试试这个。 我在这里做的是将字符串分成两个子串,并在第二个字符串中检查所有第一个字符串的anagramic对。

代表:abba

1st substring = a;

2nd substring = bba

现在检查bba中a的所有anagramic对

import java.util.*;

public class SherlockAndAnagrams{

public static void main(String[] args) {
    Scanner sc=new Scanner(System.in);
    int t=Integer.parseInt(sc.nextLine());
    while(t-->0){
        String s=sc.nextLine();
        int count=0;
        for(int i=0;i < s.length();i++){
            for(int k=i+1;k < s.length();k++){
                int num=anagram(s.substring(i,k),s.substring(i+1),s.substring(i,k).length());
                count=count+num;
            }
        }
        System.out.println(count);
    }
}
static int anagram(String s1,String s2,int len){
    int count = 0;

    char[] c1=s1.toCharArray();
    Arrays.sort(c1);
    String ss1=new String(c1);
    int length=s2.length();

    for(int i=0;i<length;i++){
        if(i+len<=length){
        String sub=s2.substring(i,i+len);
        char[] c2=sub.toCharArray();
        Arrays.sort(c2);
        String ss2=new String(c2);
        if(ss1.compareTo(ss2)==0)
            count++;
        }
    }
return count;
}

}