• 2月26-第三次机试课记录


    字符处理

    • 多组输入,看清题目

    总结和关键

    • 预处理的几种用法
      • 区间和(计算下标i到j的和):使用前缀数组, sum[i, j]=A[j] - A[i - 1];
      • 字符子串使用kmp的next数组
      • 字符子序列使用序列自动机,既一个二维数组next【n】【26】,n为长度,26为26个字母,数组的意义是下标为i的字符其对于最近的26个字母下标(1.初始化从后向前初始化,这个可以从相邻的字母比较得出,2.下标从1开始,区分于0表示没有字母,3.区分子串和子序列)
    • 字符串hash的使用,以及在这个前提下,字符串切割可以转换成为前缀和的处理,字符串循环同构可以转换成2*长数组的处理
    • kmp的书写
    • 单调队列和栈的维护,以及结合题目使用,两个都与最值相关

    题号

    • PIPIOJ 1026 a+b问题(根据题意模拟)

    • PIPIOJ 1343 PIPI的字符串问题Ⅰ(序列自动机)

    • PIPIOJ 1039 重复子序列问题(序列自动机)

    • PIPIOJ 1344 PIPI的字符串问题Ⅱ(KMP)

    • PIPIOJ 1345 PIPI的字符串问题Ⅲ(字符串HASH)

    • PIPIOJ 1346 PIPI的字符串问题Ⅳ(字符串HASH)

    • PIPIOJ 1347 PIPI的序列问题Ⅰ(单调队列)

    • PIPIOJ 1351 小鱼比可爱Ⅱ(单调栈)

    • PIPIOJ 1034 字典序最小的子序列(作为作业)

    • PIPIOJ 1348 PIPI的序列问题Ⅱ(作为作业)

    思路与技巧

    • 1343

      • 对于子序列问题使用序列自动机,初始化从后向前,下标从1开始,从而是没有字母为0,不会混淆
    • 1039

      • 同样上题
      • 但是需要注意问题分解为多个串与母串的比较
      • 这题有个坑是多组输入
    • 1344

      • 使用kmp(注意初值-1等等)

      • 与上题的区别除了在子串和子序列上,还有就是对于问题的分解上,这题同样是两个串比较可以拆分为多个子串和串比较,但是这题需要注意的是,拆分时候,可以利用next数组直接打到初始化的目的。(aaaaa和aa比较,应该是存在4个子串与aa相同,如果没有正确在两次子问题中初始化,会导致出现答案为2的错误答案)

        int kmp(){
        	int i = 0, j = 0;
        	int ans = 0; 
        	
        	while(i < lenS){
        		while(i < lenS && j < lenT){
        			if(j == -1 || s[i] == t[j]){
        				if(j + 1 == lenT){//一次子问题结束
        					ans ++;//记录
        					j = Next[j];//初始化,正好利用kmp的next数组,直接打到目的,区分上一题
        				}else{
        					i ++;
        					j ++;
        				}
        			}else
        				j = Next[j];
        		}
        	}
        	
        	return ans;
        }
        
    • 1345/1346

      • 字符hash,类似将a隐射到1, z到26这样,字符串直接对应一个数字,两个字符的比较直接变成值的比较
      • 利用预处理后,前缀和,快速剪裁出字符比如abcde的cde,直接从A【5】-A【2】*对应的权 就可以得出
      • 1345判断回文串,利用左右两次前缀和
      • 1346判断循环同构,既abababab中有几个abab的循环同构,利用将abab*2,既abababab,这样计算hash值,会自动包含所有的循环同构,比如abab【下标1-4】,baba【下标2-5(两倍的意义就在于可以用这个5)】
      • 几个计算细节
        • 关于hash
          • 计算的值可以比较大,需要使用typedef unsigned long long ull;
          • 考虑使用机制base=2333;而不是10,对应的权使用数组可以简化计算
          • 字符【l,r】=hs[r] - hs[l - 1] * pw[r - l + 1];
          • a对应1而不是0,这样做的意义在于使用字符串对应的hash,a和ab有区别
    • 1347

      • 使用单调队列,需要自己维护,使用rear和head,不需要循环队列,两端均可以插入删除
      • 其次这个限制长度为m,与之前的题目不同就在,这样的话,如果过长,删除最前的数组元素时,需要注意到要保持每个子问题中都是正的,比如:10 7 -9 8,删除10后,7和-9不再成正数,不应该出现这样的前缀了,所以这题用之前思路会很难写
      • 使用前缀和以及单调队列一下就简化了问题
    • 1351

      • 使用单调栈,还是自己维护
      • 需要注意的是从前向后初始化而不是从后向前,这样做是因为需要找到最近的大于
  • 相关阅读:
    DataGridView如何获取某个数据
    扩展方法
    base和this关键字
    装箱和拆箱
    var,object和dynamic
    const和readonly
    react native回调函数刷新页面
    react native打包android,android9.0以上版本http请求不了怎么办?
    react native中android app怎样打包发布
    React Native 实现页面返回监听
  • 原文地址:https://www.cnblogs.com/faberry/p/12369729.html
Copyright © 2020-2023  润新知