算法笔记_106:蓝桥杯练习 算法提高 周期字串(Java)

目录

1 问题描述

2 解决方案

2.1 第一印象解法(80分)

2.2 借鉴网友解法(100分)

 


1 问题描述

问题描述
  右右喜欢听故事,但是右右的妈妈总是讲一些“从前有座山,山里有座庙,庙里有个老和尚给小和尚讲故事,讲的什么呢?从前有座山……”这样循环的故事来搪塞右右。
  我们定义,如果一个字符串是以一个或者一个以上的长度为k的重复字符串所连接成的,那么这个字符串就叫做周期为k的串。
  例如:
  字符串’abcabcabcabc’周期为3,因为它是由4个循环’abc’组成的。它同样是以6为周期(两个重复的’abcabc’)和以12为周期(一个循环’abcabcabcabc’)。
  右右现在想给他的朋友大灰狼转述妈妈讲的故事,请帮他写一个程序,可以测定一个字符串的最小周期。
输入格式
  一个最大长度为100的无空格的字符串。
输出格式
  一个整数,表示输入的字符串的最小周期。
样例输入
HaHaHa
样例输出
2
样例输入
Return0
样例输出
7

 


2 解决方案

2.1 第一印象解法(80分)

初步看到此题,第一印象就是字符串模式匹配,那么遇到此问题,最佳的时间效率当然是使用KMP字符串模式匹配算法啦,结果运行测评分数为80分,原因:运行超时。

以下代码仅供参考哦。

具体代码如下:

import java.util.Scanner;

public class Main {
    
    public int[] getNext(char[] arrayB) {
        int[] next = new int[arrayB.length + 1];
        int j = 0;
        for(int i = 0;i < arrayB.length;i++) {
            while(j > 0 && arrayB[i] != arrayB[j])
                j = next[j];
            if(arrayB[j] == arrayB[i])
                j++;
            next[i + 1] = j;
        }
        return next;
    }
    
    public int getKMP(char[] arrayA, char[] arrayB) {
        int max = 0;   //统计arrayB在arrayA中匹配子串的总个数
        int[] next = getNext(arrayB);
        int j = 0;
        int tempi = -1;  //记录每一次匹配完成时i的值
        for(int i = 0;i < arrayA.length;i++) {
            while(j > 0 && arrayA[i] != arrayB[j])
                j = next[j];
            if(arrayA[i] == arrayB[j])
                j++;
            if(j == arrayB.length) {
                if(i - tempi != arrayB.length)   //针对题意运行时间要求,做出此处判定
                    break;
                tempi = i;   //更新tempi值
                max++;
                j = 0;
            }
        }
        return max;
    }
    
    public void printResult(String A) {
        char[] arrayA = A.toCharArray();
        int max = arrayA.length;
        for(int i = 0;i < arrayA.length;i++) {
            int len = i + 1;
            if(len > arrayA.length / 2)
                break;
            else if(arrayA.length % len != 0)
                continue;
            char[] arrayB = new char[len];
            for(int j = 0;j < arrayB.length;j++)
                arrayB[j] = arrayA[j];
            int tempMax = arrayA.length / arrayB.length;
            if(tempMax == getKMP(arrayA, arrayB)) {  //当匹配字符串arrayB刚好组成arrayA时
                max = arrayB.length;
                break;
            }
        }
        System.out.println(max);
        return;
    }
    
    
    public static void main(String[] args) {
        Main test = new Main();    
        Scanner in = new Scanner(System.in);
        String A = in.next();
        test.printResult(A);
    }
}

 

2.2 借鉴网友解法(100分)

具体思想如下(引用文末参考资料1中讲解):

 

具体代码如下:

import java.util.Scanner;

public class Main {
    
    public void printResult1(String A) {
        char[] arrayA = A.toCharArray();
        int max = arrayA.length;
        for(int i = 0;i < arrayA.length;i++) {
            int k = i + 1;
            if(k > arrayA.length / 2)
                break;
            else if(arrayA.length % k != 0)
                continue;
            int j = k;
            for(;j < arrayA.length;j++) {
                if(arrayA[j] != arrayA[j % k])
                    break;
            }
            if(j == arrayA.length) {
                max = k;
                break;
            }
        }
        System.out.println(max);
        return;
    }
    
    public static void main(String[] args) {
        Main test = new Main();    
        Scanner in = new Scanner(System.in);
        String A = in.next();
        test.printResult1(A);
    }
}

 

 

 

参考资料:

1.【算法-字符串】【周期串】

 

posted @ 2017-03-21 13:45  舞动的心  阅读(1125)  评论(0编辑  收藏  举报