zoukankan      html  css  js  c++  java
  • SYZOJ 186 [额]你猜是不是DP(哈希+二分答案+二分搜索)

     

    题目描述

    现在给两个包含小写字母的字符串a,b ,求a 与b的最长公共连续子串的长度。

    输入格式

    两个字符串

    输出格式

    一个整数,为输入的两个字符串的最长公共连续子串的长度

    测试样例

    输入

    qaqaaaq
    qqaqa
    

    输出

    4
    

    解释

    最长连续公共子串为qaqa,长度为4

    数据范围与提示

    20 组测试数据

    对于20%的数据,a,b长度 ∈ [1, 200]

    对于50%的数据,a,b长度 ∈ [1, 20000]

    对于100%的数据, a,b长度 ∈ [1, 200000] 

    题目链接:SYZOJ 186

    哈希第一题,预处理出前缀hash值后二分答案,这里需要用二分优化,把第一个和第二个字符串的所有以mid为长度的区间哈希值储存并对后者排序,那么只要遍历第一个字符串的区间哈希值的时候二分查找第二段是否存在同样的哈希值即可。若二分+双for循环遍历的复杂度$O(logN*N^2)$只有85分会超时,改成二分搜索复杂度就成了$O(logN*NlogN)$就不会超时了,突然发现哈希有时候是个神器,只是写起来有点麻烦而且对于hash killer这种题目就比较尴尬了

    代码:

    #include <stdio.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    typedef unsigned long long ULL;
    const double PI = acos(-1.0);
    const int N = 200010;
    const ULL seed = 1e9 + 7;
    ULL prefix[N], pa[N], pb[N], ha[N], hb[N];
    char a[N], b[N];
    ULL vec[N];
    
    void init()
    {
        prefix[0] = 1ull;
        for (int i = 1; i < N; ++i)
            prefix[i] = prefix[i - 1] * seed;
    }
    int main(void)
    {
        int i, j;
        init();
        while (~scanf("%s%s", a + 1, b + 1))
        {
            int la = strlen(a + 1);
            int lb = strlen(b + 1);
            pa[0] = pb[0] = 0;
            for (i = 1; i <= la; ++i)
                pa[i] = pa[i - 1] * seed + a[i];
            for (i = 1; i <= lb; ++i)
                pb[i] = pb[i - 1] * seed + b[i];
            int ans = 0, L = 0, R = min(la, lb);
            while (L <= R)
            {
                int mid = (L + R) >> 1;
                int flag = 0;
                int sa = 0, sb = 0;
                for (i = mid; i <= la; ++i)
                    ha[sa++] = pa[i] - pa[i - mid] * prefix[mid];
                for (i = mid; i <= lb; ++i)
                    hb[sb++] = pb[i] - pb[i - mid] * prefix[mid];
                sort(hb, hb + sb);
                for (i = 0; i < sa; ++i)
                {
                    if (binary_search(hb, hb + sb, ha[i]))
                    {
                        flag = 1;
                        break;
                    }
                }
                if (flag)
                {
                    ans = mid;
                    L = mid + 1;
                }
                else
                    R = mid - 1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    2277 爱吃皮蛋的小明
    zoj2314 经典 无源汇有上下界最大流 并输出可行流
    [置顶] css3 befor after 简单使用 制作时尚焦点图相框
    [置顶] 程序员的奋斗史(二十八)——寒门再难出贵子?
    TaintDroid:智能手机监控实时隐私信息流跟踪系统(四)
    Activity切换效果(overridePendingTransition)
    Activity生命周期,状态保存恢复(经典)
    大二实习使用的技术汇总(上)
    Struts2配置RESULT中TYPE的参数说明
    关于程序动态库链接和运行时搜索路径设置的个人理解
  • 原文地址:https://www.cnblogs.com/Blackops/p/6661547.html
Copyright © 2011-2022 走看看