周期性弦乐

时间:2012-11-16 10:04:22

标签: java string

我正在尝试解决这个String manipulation问题,我需要找到给定字符串的最小句点。


如果字符串可以通过连接另一个长度为k的字符串的一个或多个重复来形成,则称该字符串具有句点k。


例如,字符串“abcabcabcabc”具有句点3,因为它是由字符串“abc”的4次重复形成的。它还有6期(两次重复的“abcabc”)和12次(一次重复的“abcabcabcabc”)。这是我的代码:


public static int getPeriod(String str){
    int len=str.length();   
    boolean flag=false;
    int i;

    for (i=0;i<len;i++){
        String s=str.substring(0,i);
        String tmp=str;

        while(tmp.length()>0){
            if(tmp.startsWith(s)){
                tmp=tmp.substring(0,i);
                flag=true;
            }

            else {
                flag=false;
                continue;
            }
        }

        if (flag==true)
            break;
    }

    return i;
 }

我通过循环原始字符串形成一个字符串s,一次一个字符。之后,我正在检查原始字符串是否可以通过连接字符串s任意次数而完全耗尽。


错误:

  

该方法始终返回0.

     

为什么会这样?


编辑:我的算法

让我们考虑输入字符串HoHoHo

First step: s=H
        tmp= HoHoHo
        tmp= oHoHo (after substringing tmp)
        'o' isn't the same as s, so we increase i



   Second step:s=Ho
            tmp= HoHoHo
            tmp= HoHo (after substringing tmp)
            tmp= Ho (after substringing tmp)
            tmp= "" (after substringing tmp)

Return the value of i, that is 2.

4 个答案:

答案 0 :(得分:3)

while循环中的代码不正确,在第一次使用i=0调用for循环时调用它,因此对tmp变量的第一次赋值将其设置为空字符串,循环退出,你得到0.标志分配和continue中的else也不正确。 试试这个:

public static int getPeriod(String str) {
    int len = str.length();
    int i;

    for (i = 1; i <= len/2; i++) {
        String period = str.substring(0, i);
        String tmp = str;
        boolean flag = true;

        while (flag && tmp.length() > 0) {
            if (tmp.startsWith(period)) {
                tmp = tmp.substring(i);
            } else {
                flag = false;
            }
        }

        if (flag == true) {
            return i;
        }
    }
    return 0;
}

请注意,for循环从1开始并转到len/2,因为您不想检查零长度期,并且不能有超过{的{ {1}}。

答案 1 :(得分:2)

在第一次循环迭代中,i == 0,因此s是“”(空字符串),并且在while循环的第一次迭代之后tmp也是“”,因此tmp也变为“”并退出所有循环。

答案 2 :(得分:1)

从i = 0开始将始终返回true,因为substring(0,0)将返回“”字符串并且tmp.startsWith(“”)始终为true。

首先你应该从1开始我,你也应该用continue替换break,因为continue会继续你的while loop,但你想做的是{{ 1}} continue而不是while循环

以下是您的代码的一个版本:

for loop

答案 3 :(得分:0)

我知道这是一个老问题。使用Knuth的Prefix函数可以在线性时间内解决该问题。

  public static int prefixFunction(final String needle)
    {
        //This code does not include input validation. Validate the input and return appropriate error message

        int[] pf = new int[needle.length()];
        for (int i = 1; i < needle.length(); i++)
        {
            int j = pf[i - 1];
            while (j > 0 && needle.charAt(i) != needle.charAt(j)) j--;
            if (needle.charAt(i) == needle.charAt(j)) ++j;
            pf[i] = j;
        }
        int n = needle.length(), maxValue = pf[n - 1];
        if(maxValue == 0 || n%(n-maxValue) != 0) return -1; //Not periodic 
        return needle.length() - maxValue;
    }