题解 | #白兔的字符串#

白兔的字符串

https://ac.nowcoder.com/acm/problem/15253

Java版看这里

已知目标串为str,需要再strs里面遍历寻找每一个母串所含有的子串的循环同构的串,那针对已知的子串,可以预处理得到所有目标子串,我们再将所有目标串放入Set中,方便后续判断。

具体做法为: 如果有一个串为:abcd 那么其循环同构的串即为 abcd + abc = abcdabc 中的所有长度为原串长度的子串

abcd abc | a bcda bc | ab cdab c |abc dabc

后续的子串个数比较即为基础的字符串hash

附上AC代码:

import java.io.*;
import java.util.*;

public class Main {
    public static Scanner sc = new Scanner(System.in);
    public static BufferedReader re = new BufferedReader(new InputStreamReader(System.in));// 快速输入
    public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));// 快速输出

    public static final int N = 131;
    public static long[] p = new long[1000001];

    public static void main(String[] args) throws IOException {
        init();
        String str = sc.next();
        int n = str.length();
      	// 更新str并计算所有目标子串,将其放入Set中
        str += str.substring(0, str.length() - 1);

        long[] tn = new long[str.length()];
        tn[0] = str.charAt(0);
        for (int i = 1; i < str.length(); i++) {
            tn[i] = tn[i - 1] * N + str.charAt(i);
        }

        Set<Long> ts = new HashSet<>();
        for (int i = 0; i <= str.length() - n; i++) {
            long tmp=get(tn, i, i + n - 1);
            ts.add(tmp);
        }

      	// 遍历所有母串
        int t = sc.nextInt();
        while (t-- > 0) {
            str = sc.next();
			
          	// 计算当前母串的hash数组(计算方法和之前的str一样)
            tn = new long[str.length()];
            tn[0] = str.charAt(0);
            for (int i = 1; i < str.length(); i++) {
                tn[i] = tn[i - 1] * N + str.charAt(i);
            }
            
            // 寻找目标串
            int cnt = 0;
            for (int i = 0; i <= str.length() - n; i++) {
                // 判断每一个长度为n的子串
                long tmp=get(tn, i, i + n - 1);
                if (ts.contains(tmp)) {
                    cnt++;
                }
            }
            System.out.println(cnt);
        }
    }

    public static void init() {
      	// 初始化N的幂数组
        p[0] = 1;
        for (int i = 1; i < 1000001; i++) {
            p[i] = p[i-1] * N;
        }
    }

    public static long get(long[] nums, int l, int r) {
      	//通过传入的hash数组和截取范围返回对应的hash值(包头包尾)
        return l == 0 ? nums[r] : (nums[r] - p[r - l + 1] * nums[l - 1]);
    }
}
全部评论

相关推荐

01-18 22:21
门头沟学院 Java
26届公办二本,目前在上海某二游中厂测试实习中两个多月了,准备下周问leader能不能转正,但感觉希望渺茫25年初时,我的目标还是后端开发,能够找到合适的暑期实习在秋招找寻机会。那段时间我一直都在欺骗自己,时间还早,小厂要求低。项目是抄的,算法是不刷的,八股是背了就忘的,直到七月才发现自己只有crud的能力,遂选择了一家互联网小厂去干功能测试。在这段实习我感觉什么都没有学到,只是一味的点点点,写在简历上的经历能把自己逗乐。秋招果然大败而归,于是在十一月初接下了一家二次元游戏公司的测试实习。新公司的氛围很好,管理扁平,日常福利也很多。虽然平时的会议也会参加,同事们也很友好,但是我仍感觉没有什么归属感。我肯定是非常想要能够转正的,一面面试官也说有转正机会,但hr面却和我说明是日常实习。我很喜欢这里,但可能没有太大的机会,所以我肯定是要去参加春招的。但最近考虑到春招的hc情况,我是又着急又难受。前几天公司举办了年会,这种情况达到了顶点,我连续三天失眠到凌晨四点,心里全在想如果找不到工作该怎么办。其实我知道,并不是我找不到,而是眼高手低,甚至秋招我只在各官网投,ssob没有任何投递。而且我选择游测完全是因为自己的二次元属性,春招也有特别意向的库洛,我甚至是因此才来这边实习的。但我害怕库洛给不了我机会,更害怕没有其他机会。在异地出租屋没有朋友,颈椎不舒服,睡眠越来越差,甚至痔疮越来越严重,烟也越抽越多,我真的害怕自己的身体再来些啥毛病春招啊,给我些运气吧。
星辰尽头:保持平常的心态,做该做的事情就好,要相信一切会水到渠成
春招启动,你开始投递了吗...
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务