你好我们给了家庭作业问题,它要求我找到一个字符串的所有不同的子串。 我已经实现了一个方法,它将告诉你字符串的所有子字符串,但我需要一个帮助,弄清楚如何不计算一个已被计入一次作为子字符串,因为赋值是找到不同的一个。
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
弗雷德
答案 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返回最大值。
这不是我原来的答案。我只是链接到它并粘贴它以防链接断开。
答案 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);}