zoukankan      html  css  js  c++  java
  • 2020杭电多校第二场 hdu6774 String Distance

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=6774

    题目大意

    给定一个字符串 A 和一个字符串 B , 有 Q 次查询

    每次查询给出一段区间 [L , R] , 问 A[L...R] 和 B串的 LCS 为多少

    解题思路 

    定义 M 为 B 串的长度 , 先预处理跑一遍序列自动机 NEX 

    其中 nex[ i ][ j ] 表示字符串 A 的 [ i + 1 , n ] 区间第一次出现字符 j 的位置

    定义 dp [ i ][ j ] , 其含义为 —— 和B的前 i 个字符 , 匹配了长度为 j 的 LCS 的最短 A 前缀

    即 LCS( B[1...i] , A[L...X] ) = j , X 为最小取值 , dp[ i ][ j ] = X 

    再定义 pre = dp[ i - 1 ][ j - 1 ] , 那么

    ①、dp[ i ][ j ] = NEX[ pre ][ b[i] - 'a' ] 

    ②、dp[ i ][ j ] = dp[ i - 1 ][ j ]

    当 dp[ i ][ j ] 的值小于等于 R 时 ,  LCS = j 合法

    所以最后我们只要从 M 到 1 找到第一个 j 使得 dp[ M ][ j ] <= R 即可

    AC_Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 3e5 + 10 , M = 30;
    int dp[N][M] , nex[N][M];
    char a[N] , b[M];
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0) , cout.tie(0);
        int T ;
        cin >> T ;
        while(T --)
        {
            cin >> a + 1 >> b + 1;
            int n = strlen(a + 1) , m = strlen(b + 1) , q;
            for(int j = 0 ; j < 26 ; j ++) nex[n][j] = n + 1;
            for(int i = n - 1 ; i >= 0 ; i --)
            {
                for(int j = 0 ; j < 26 ; j ++) nex[i][j] = nex[i + 1][j];
                nex[i][a[i + 1] - 'a'] = i + 1; 
            }
            cin >> q; 
            while(q --)
            {
                int l , r , lcs = 0;
                cin >> l >> r;
                for(int i = 0 ; i <= m ; i ++) for(int j = 0 ; j <= m ; j ++) dp[i][j] = 0x3f3f3f3f; 
                for(int i = 0 ; i <= m ; i ++) dp[i][0] = l - 1;
                for(int i = 1 ; i <= m ; i ++)
                    for(int j = 1 ;  j <= i ; j ++)
                    {
                        if(dp[i - 1][j] <= r) dp[i][j] = min(dp[i][j] , dp[i - 1][j]);
                        int pre = dp[i - 1][j - 1];
                        if(pre <= r && nex[pre][b[i] - 'a'] != 0 && nex[pre][b[i] - 'a'] <= r)
                        dp[i][j] = min(dp[i][j] , nex[pre][b[i] - 'a']);
                    }
                   for(int i = m ; i >= 1 ; i --) if(dp[m][i] <= r) { lcs = i ; break ; }
                cout << r - l + 1 + m - 2 * lcs << '
    ';    
            }
        }
        return 0;
    }
  • 相关阅读:
    如何不传入对象就获得某对象的方法---ThreadLocal类
    Linux系统主目录被更改,怎么修改回去?
    tree命令的安装
    Linux命令学习man
    当重载函数的参数是Object和Object数组的时候会发生什么情况!!!
    Linux学习(二)之内核、系统调用、库
    使用puttygen转换OpenSSH SSH2私钥为RSA PEM格式
    docker-compose使用详解
    svn迁移到gitlab
    linux快速启动http端口
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13369855.html
Copyright © 2011-2022 走看看