查找字符串的所有不同子字符串

时间:2012-11-03 21:39:59

标签: java string substring

你好我们给了家庭作业问题,它要求我找到一个字符串的所有不同的子串。 我已经实现了一个方法,它将告诉你字符串的所有子字符串,但我需要一个帮助,弄清楚如何不计算一个已被计入一次作为子字符串,因为赋值是找到不同的一个。

public int printSubstrings1(int length)
{ 
    for(int i=0; i<text.length()-length+1;i++)
    {
        String sub = text.substring(i,length+i);

        counter++;
    }
    return counter;

}

这里我传递了我想要的字符串的长度。 我通过另一种方法做到这一点。

所以给出的示例字符串是“fred”,而不同的子字符串将是10.我的方法将输出正确的答案,因为字符串不包含任何重复的字母。我被困在我重复的子串上。

如果我输入fred。这就是我的方法输出

长度1
˚F
[R
Ë
d
长度2
FR
重新
编辑
长度3
FRE

长度4
弗雷德

6 个答案:

答案 0 :(得分:3)

public ArrayList<String> getAllUniqueSubset(String str) {
        ArrayList<String> set = new ArrayList<String>();
        for (int i = 0; i < str.length(); i++) {
            for (int j = 0; j < str.length() - i; j++) {
                String elem = str.substring(j, j + (i+1));
                if (!set.contains(elem)) {
                    set.add(elem);
                }
            }
        }
        return set;
    }

答案 1 :(得分:2)

此处示例为Set

public int printSubstrings1(int length) {
    Set<String> set = new HashSet<String>();
    for(int i=0; i < text.length() - length + 1; i++) {
        String sub = text.substring(i,length+i);
        set.add(sub);
    }
    for (String str : set) {
        System.out.println(str);
    }
    return set.size();
}

答案 2 :(得分:0)

将任何新的子字符串插入数组并检查它是否已经可用,不要将其添加到数组中。完成后循环遍历数组并打印出不同的子字符串。

要检查数组中是否存在元素,请创建一个将数组和值作为参数的函数。如果发现返回true,它将遍历数组寻找值。退出循环返回false。

e.g。

public static boolean(String target, String[] arr)
{
  for(int i = 0; i < arr.length; i++){
      if(arr[i].equals(target))
         return true;
  }
   return false;
}

答案 3 :(得分:0)

该算法仅使用Z-function / Z算法。

对于单词的每个前缀i,将其反转并对其执行z_function。 以i结尾的新的不同子字符串的数量为(the length of the prefix) — (maximum value in the z_function array)。 伪代码如下所示:

string s; cin >> s;
int sol = 0
foreach i to s.size()-1
    string x = s.substr( 0 , i+1 );
    reverse( x.begin() , x.end() );
    vector<int> z = z_function( x );
    //this works too
    //vector<int> z = prefix_functionx(x); 
    int mx = 0;
    foreach j to x.size()-1
        mx = max( mx , z[j] );
    sol += (i+1) - mx; 

cout << sol;

该算法的时间复杂度为O(n ^ 2)。也可以从z_function返回最大值。

Source.

这不是我原来的答案。我只是链接到它并粘贴它以防链接断开。

答案 4 :(得分:0)

我遵循了link。确认了quora中类似答案的内容

解决方案包括构造后缀数组,然后根据最长公共前缀查找不同子串的数量。

这里的一个关键观点是:

如果查看字符串的每个后缀的前缀,则表示已覆盖该字符串的所有子字符串。

让我们举一个例子:BANANA

后缀为:0)BANANA 1)ANANA 2)NANA 3)ANA 4)NA 5)A

如果我们对上面的后缀进行排序,那么通过前缀会容易得多,因为我们可以轻松地跳过重复的前缀。

后缀分类:5)A 3)ANA 1)ANANA 0)BANANA 4)NA 2)NANA

从现在开始,

LCP = 2个字符串的最长公共前缀。

初​​始化

ans = length(第一个后缀)= length(“A”)= 1.

现在从上面的排序后缀中考虑连续的后缀对,即[A,ANA],[ANA,ANANA],[ANANA,BANANA]等。

我们可以看到,LCP(“A”,“ANA”)=“A”。

不属于公共前缀的所有字符都会产生不同的子字符串。在上述情况下,它们是'N'和'A'。所以他们应该被添加到ans。

所以我们有,1 2 ans + =长度(“ANA”) - LCP(“A”,“ANA”)ans = ans + 3 - 1 = ans + 2 = 3

对下一对连续后缀执行相同操作:[“ANA”,“ANANA”]

1 2 3 4 LCP(“ANA”,“ANANA”)=“ANA”。 ans + = length(“ANANA”) - 长度(LCP)=&gt; ans = ans + 5 - 3 =&gt; ans = 3 + 2 = 5.

同样,我们有:

1 2 LCP(“ANANA”,“BANANA”)= 0 ans = ans + length(“BANANA”) - 0 = 11

1 2 LCP(“BANANA”,“NA”)= 0 ans = ans + length(“NA”) - 0 = 13

1 2 LCP(“NA”,“NANA”)= 2 ans = ans + length(“NANA”) - 2 = 15

因此字符串“BANANA”的不同子串的数量= 15。

答案 5 :(得分:0)

您可以通过两种方式执行此操作,不确定您的老师是否允许,但我将使用HashSet来实现唯一性。

不使用'substring()':

void uniqueSubStrings(String test) {
HashSet < String > substrings = new LinkedHashSet();
char[] a = test.toCharArray();
for (int i = 0; i < test.length(); i++) {
    substrings.add(a[i] + "");
    for (int j = i + 1; j < test.length(); j++) {
        StringBuilder sb = new StringBuilder();
        for (int k = i; k <= j; k++) {
            sb.append(a[k]);
        }
        substrings.add(sb.toString());
    }
}
System.out.println(substrings);

}

使用“子字符串”:

    void uniqueSubStringsWithBuiltIn(String test) {
    HashSet<String> substrings = new LinkedHashSet();

    for(int i=0; i<test.length();i++) {
        for(int j=i+1;j<test.length()+1;j++) {
            substrings.add(test.substring(i, j));
        }
    }
        System.out.println(substrings);}